blob: a3db2ee17b660b6bb572435b946cdcbf63f92435 [file] [log] [blame]
zmo@google.com5601ea02011-06-10 18:23:25 +00001//
Nicolas Capens16004fc2014-06-11 11:29:11 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
zmo@google.com5601ea02011-06-10 18:23:25 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/OutputGLSLBase.h"
8#include "compiler/translator/compilerdebug.h"
zmo@google.com5601ea02011-06-10 18:23:25 +00009
daniel@transgaming.com773ff742013-01-11 04:12:51 +000010#include <cfloat>
daniel@transgaming.com6c1203f2013-01-11 04:12:43 +000011
zmo@google.com5601ea02011-06-10 18:23:25 +000012namespace
13{
Zhenyao Mo9eedea02014-05-12 16:02:35 -070014TString arrayBrackets(const TType &type)
zmo@google.com5601ea02011-06-10 18:23:25 +000015{
16 ASSERT(type.isArray());
17 TInfoSinkBase out;
18 out << "[" << type.getArraySize() << "]";
19 return TString(out.c_str());
20}
21
Zhenyao Mo9eedea02014-05-12 16:02:35 -070022bool isSingleStatement(TIntermNode *node)
23{
24 if (const TIntermAggregate *aggregate = node->getAsAggregate())
zmo@google.com5601ea02011-06-10 18:23:25 +000025 {
26 return (aggregate->getOp() != EOpFunction) &&
27 (aggregate->getOp() != EOpSequence);
28 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -070029 else if (const TIntermSelection *selection = node->getAsSelectionNode())
zmo@google.com5601ea02011-06-10 18:23:25 +000030 {
31 // Ternary operators are usually part of an assignment operator.
32 // This handles those rare cases in which they are all by themselves.
33 return selection->usesTernaryOperator();
34 }
35 else if (node->getAsLoopNode())
36 {
37 return false;
38 }
39 return true;
40}
41} // namespace
42
Zhenyao Mo9eedea02014-05-12 16:02:35 -070043TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +000044 ShArrayIndexClampingStrategy clampingStrategy,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000045 ShHashFunction64 hashFunction,
Zhenyao Mo9eedea02014-05-12 16:02:35 -070046 NameMap &nameMap,
47 TSymbolTable &symbolTable,
Jamie Madill02f20dd2013-09-12 12:07:42 -040048 int shaderVersion)
zmo@google.com5601ea02011-06-10 18:23:25 +000049 : TIntermTraverser(true, true, true),
50 mObjSink(objSink),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000051 mDeclaringVariables(false),
shannon.woods@transgaming.com1d432bb2013-01-25 21:57:28 +000052 mClampingStrategy(clampingStrategy),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000053 mHashFunction(hashFunction),
54 mNameMap(nameMap),
Jamie Madill02f20dd2013-09-12 12:07:42 -040055 mSymbolTable(symbolTable),
56 mShaderVersion(shaderVersion)
zmo@google.com5601ea02011-06-10 18:23:25 +000057{
58}
59
Zhenyao Mo9eedea02014-05-12 16:02:35 -070060void TOutputGLSLBase::writeTriplet(
61 Visit visit, const char *preStr, const char *inStr, const char *postStr)
zmo@google.com5601ea02011-06-10 18:23:25 +000062{
Zhenyao Mo9eedea02014-05-12 16:02:35 -070063 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +000064 if (visit == PreVisit && preStr)
zmo@google.com5601ea02011-06-10 18:23:25 +000065 out << preStr;
zmo@google.com5601ea02011-06-10 18:23:25 +000066 else if (visit == InVisit && inStr)
zmo@google.com5601ea02011-06-10 18:23:25 +000067 out << inStr;
zmo@google.com5601ea02011-06-10 18:23:25 +000068 else if (visit == PostVisit && postStr)
zmo@google.com5601ea02011-06-10 18:23:25 +000069 out << postStr;
zmo@google.com5601ea02011-06-10 18:23:25 +000070}
71
Zhenyao Mo9eedea02014-05-12 16:02:35 -070072void TOutputGLSLBase::writeBuiltInFunctionTriplet(
73 Visit visit, const char *preStr, bool useEmulatedFunction)
zmo@google.com5601ea02011-06-10 18:23:25 +000074{
Zhenyao Mo9eedea02014-05-12 16:02:35 -070075 TString preString = useEmulatedFunction ?
76 BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr;
77 writeTriplet(visit, preString.c_str(), ", ", ")");
78}
79
80void TOutputGLSLBase::writeVariableType(const TType &type)
81{
82 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +000083 TQualifier qualifier = type.getQualifier();
Jamie Madill3b5c2da2014-08-19 15:23:32 -040084 if (qualifier != EvqTemporary && qualifier != EvqGlobal)
Jamie Madill1c28e1f2014-08-04 11:37:54 -040085 {
zmo@google.com5601ea02011-06-10 18:23:25 +000086 out << type.getQualifierString() << " ";
Jamie Madill1c28e1f2014-08-04 11:37:54 -040087 }
zmo@google.com5601ea02011-06-10 18:23:25 +000088 // Declare the struct if we have not done so already.
Zhenyao Mo9eedea02014-05-12 16:02:35 -070089 if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
zmo@google.com5601ea02011-06-10 18:23:25 +000090 {
Jamie Madill01f85ac2014-06-06 11:55:04 -040091 TStructure *structure = type.getStruct();
92
93 declareStruct(structure);
94
95 if (!structure->name().empty())
96 {
97 mDeclaredStructs.insert(structure->uniqueId());
98 }
zmo@google.com5601ea02011-06-10 18:23:25 +000099 }
100 else
101 {
102 if (writeVariablePrecision(type.getPrecision()))
103 out << " ";
104 out << getTypeName(type);
105 }
106}
107
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700108void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
zmo@google.com5601ea02011-06-10 18:23:25 +0000109{
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700110 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +0000111 for (TIntermSequence::const_iterator iter = args.begin();
112 iter != args.end(); ++iter)
113 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700114 const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
zmo@google.com5601ea02011-06-10 18:23:25 +0000115 ASSERT(arg != NULL);
116
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700117 const TType &type = arg->getType();
zmo@google.com189be2f2011-06-16 18:28:53 +0000118 writeVariableType(type);
zmo@google.com5601ea02011-06-10 18:23:25 +0000119
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700120 const TString &name = arg->getSymbol();
zmo@google.com5601ea02011-06-10 18:23:25 +0000121 if (!name.empty())
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000122 out << " " << hashName(name);
zmo@google.com5601ea02011-06-10 18:23:25 +0000123 if (type.isArray())
124 out << arrayBrackets(type);
125
126 // Put a comma if this is not the last argument.
127 if (iter != args.end() - 1)
128 out << ", ";
129 }
130}
131
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700132const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
133 const TType &type, const ConstantUnion *pConstUnion)
zmo@google.com5601ea02011-06-10 18:23:25 +0000134{
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700135 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +0000136
137 if (type.getBasicType() == EbtStruct)
138 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700139 const TStructure *structure = type.getStruct();
Jamie Madill98493dd2013-07-08 14:39:03 -0400140 out << hashName(structure->name()) << "(";
141
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700142 const TFieldList &fields = structure->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -0400143 for (size_t i = 0; i < fields.size(); ++i)
zmo@google.com5601ea02011-06-10 18:23:25 +0000144 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700145 const TType *fieldType = fields[i]->type();
zmo@google.com5601ea02011-06-10 18:23:25 +0000146 ASSERT(fieldType != NULL);
147 pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700148 if (i != fields.size() - 1)
149 out << ", ";
zmo@google.com5601ea02011-06-10 18:23:25 +0000150 }
151 out << ")";
152 }
153 else
154 {
Jamie Madill94bf7f22013-07-08 13:31:15 -0400155 size_t size = type.getObjectSize();
zmo@google.com5601ea02011-06-10 18:23:25 +0000156 bool writeType = size > 1;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700157 if (writeType)
158 out << getTypeName(type) << "(";
Jamie Madill94bf7f22013-07-08 13:31:15 -0400159 for (size_t i = 0; i < size; ++i, ++pConstUnion)
zmo@google.com5601ea02011-06-10 18:23:25 +0000160 {
161 switch (pConstUnion->getType())
162 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700163 case EbtFloat:
164 out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst()));
165 break;
166 case EbtInt:
167 out << pConstUnion->getIConst();
168 break;
169 case EbtBool:
170 out << pConstUnion->getBConst();
171 break;
172 default: UNREACHABLE();
zmo@google.com5601ea02011-06-10 18:23:25 +0000173 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700174 if (i != size - 1)
175 out << ", ";
zmo@google.com5601ea02011-06-10 18:23:25 +0000176 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700177 if (writeType)
178 out << ")";
zmo@google.com5601ea02011-06-10 18:23:25 +0000179 }
180 return pConstUnion;
181}
182
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700183void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000184{
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700185 TInfoSinkBase &out = objSink();
Zhenyao Mo550c6002014-02-26 15:40:48 -0800186 if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node))
187 out << mLoopUnrollStack.getLoopIndexValue(node);
zmo@google.com5601ea02011-06-10 18:23:25 +0000188 else
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000189 out << hashVariableName(node->getSymbol());
zmo@google.com5601ea02011-06-10 18:23:25 +0000190
191 if (mDeclaringVariables && node->getType().isArray())
192 out << arrayBrackets(node->getType());
193}
194
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700195void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000196{
197 writeConstantUnion(node->getType(), node->getUnionArrayPointer());
198}
199
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700200bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000201{
202 bool visitChildren = true;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700203 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +0000204 switch (node->getOp())
205 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700206 case EOpInitialize:
207 if (visit == InVisit)
208 {
209 out << " = ";
210 // RHS of initialize is not being declared.
211 mDeclaringVariables = false;
212 }
213 break;
214 case EOpAssign:
215 writeTriplet(visit, "(", " = ", ")");
216 break;
217 case EOpAddAssign:
218 writeTriplet(visit, "(", " += ", ")");
219 break;
220 case EOpSubAssign:
221 writeTriplet(visit, "(", " -= ", ")");
222 break;
223 case EOpDivAssign:
224 writeTriplet(visit, "(", " /= ", ")");
225 break;
Olli Etuahoff805cc2015-02-13 10:59:34 +0200226 case EOpIModAssign:
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +0000227 writeTriplet(visit, "(", " %= ", ")");
228 break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700229 // Notice the fall-through.
230 case EOpMulAssign:
231 case EOpVectorTimesMatrixAssign:
232 case EOpVectorTimesScalarAssign:
233 case EOpMatrixTimesScalarAssign:
234 case EOpMatrixTimesMatrixAssign:
235 writeTriplet(visit, "(", " *= ", ")");
236 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200237 case EOpBitShiftLeftAssign:
238 writeTriplet(visit, "(", " <<= ", ")");
239 break;
240 case EOpBitShiftRightAssign:
241 writeTriplet(visit, "(", " >>= ", ")");
242 break;
243 case EOpBitwiseAndAssign:
244 writeTriplet(visit, "(", " &= ", ")");
245 break;
246 case EOpBitwiseXorAssign:
247 writeTriplet(visit, "(", " ^= ", ")");
248 break;
249 case EOpBitwiseOrAssign:
250 writeTriplet(visit, "(", " |= ", ")");
251 break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700252
253 case EOpIndexDirect:
254 writeTriplet(visit, NULL, "[", "]");
255 break;
256 case EOpIndexIndirect:
257 if (node->getAddIndexClamp())
258 {
zmo@google.com5601ea02011-06-10 18:23:25 +0000259 if (visit == InVisit)
260 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700261 if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
262 out << "[int(clamp(float(";
263 else
264 out << "[webgl_int_clamp(";
zmo@google.com5601ea02011-06-10 18:23:25 +0000265 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700266 else if (visit == PostVisit)
267 {
268 int maxSize;
269 TIntermTyped *left = node->getLeft();
270 TType leftType = left->getType();
zmo@google.com5601ea02011-06-10 18:23:25 +0000271
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700272 if (left->isArray())
273 {
274 // The shader will fail validation if the array length is not > 0.
275 maxSize = leftType.getArraySize() - 1;
276 }
277 else
278 {
279 maxSize = leftType.getNominalSize() - 1;
280 }
281
282 if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
283 out << "), 0.0, float(" << maxSize << ")))]";
284 else
285 out << ", 0, " << maxSize << ")]";
286 }
287 }
288 else
289 {
zmo@google.com5601ea02011-06-10 18:23:25 +0000290 writeTriplet(visit, NULL, "[", "]");
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700291 }
292 break;
293 case EOpIndexDirectStruct:
294 if (visit == InVisit)
295 {
296 // Here we are writing out "foo.bar", where "foo" is struct
297 // and "bar" is field. In AST, it is represented as a binary
298 // node, where left child represents "foo" and right child "bar".
299 // The node itself represents ".". The struct field "bar" is
300 // actually stored as an index into TStructure::fields.
301 out << ".";
302 const TStructure *structure = node->getLeft()->getType().getStruct();
303 const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
304 const TField *field = structure->fields()[index->getIConst(0)];
305
306 TString fieldName = field->name();
307 if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
308 fieldName = hashName(fieldName);
309
310 out << fieldName;
311 visitChildren = false;
312 }
313 break;
314 case EOpVectorSwizzle:
315 if (visit == InVisit)
316 {
317 out << ".";
318 TIntermAggregate *rightChild = node->getRight()->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700319 TIntermSequence *sequence = rightChild->getSequence();
320 for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit)
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000321 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700322 TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
323 ASSERT(element->getBasicType() == EbtInt);
324 ASSERT(element->getNominalSize() == 1);
325 const ConstantUnion& data = element->getUnionArrayPointer()[0];
326 ASSERT(data.getType() == EbtInt);
327 switch (data.getIConst())
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000328 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700329 case 0:
330 out << "x";
331 break;
332 case 1:
333 out << "y";
334 break;
335 case 2:
336 out << "z";
337 break;
338 case 3:
339 out << "w";
340 break;
341 default:
342 UNREACHABLE();
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000343 }
344 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700345 visitChildren = false;
346 }
347 break;
daniel@transgaming.com97b16d12013-02-01 03:20:42 +0000348
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700349 case EOpAdd:
350 writeTriplet(visit, "(", " + ", ")");
351 break;
352 case EOpSub:
353 writeTriplet(visit, "(", " - ", ")");
354 break;
355 case EOpMul:
356 writeTriplet(visit, "(", " * ", ")");
357 break;
358 case EOpDiv:
359 writeTriplet(visit, "(", " / ", ")");
360 break;
Olli Etuahoff805cc2015-02-13 10:59:34 +0200361 case EOpIMod:
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +0000362 writeTriplet(visit, "(", " % ", ")");
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700363 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200364 case EOpBitShiftLeft:
365 writeTriplet(visit, "(", " << ", ")");
366 break;
367 case EOpBitShiftRight:
368 writeTriplet(visit, "(", " >> ", ")");
369 break;
370 case EOpBitwiseAnd:
371 writeTriplet(visit, "(", " & ", ")");
372 break;
373 case EOpBitwiseXor:
374 writeTriplet(visit, "(", " ^ ", ")");
375 break;
376 case EOpBitwiseOr:
377 writeTriplet(visit, "(", " | ", ")");
378 break;
379
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700380 case EOpEqual:
381 writeTriplet(visit, "(", " == ", ")");
382 break;
383 case EOpNotEqual:
384 writeTriplet(visit, "(", " != ", ")");
385 break;
386 case EOpLessThan:
387 writeTriplet(visit, "(", " < ", ")");
388 break;
389 case EOpGreaterThan:
390 writeTriplet(visit, "(", " > ", ")");
391 break;
392 case EOpLessThanEqual:
393 writeTriplet(visit, "(", " <= ", ")");
394 break;
395 case EOpGreaterThanEqual:
396 writeTriplet(visit, "(", " >= ", ")");
397 break;
daniel@transgaming.com97b16d12013-02-01 03:20:42 +0000398
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700399 // Notice the fall-through.
400 case EOpVectorTimesScalar:
401 case EOpVectorTimesMatrix:
402 case EOpMatrixTimesVector:
403 case EOpMatrixTimesScalar:
404 case EOpMatrixTimesMatrix:
405 writeTriplet(visit, "(", " * ", ")");
406 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000407
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700408 case EOpLogicalOr:
409 writeTriplet(visit, "(", " || ", ")");
410 break;
411 case EOpLogicalXor:
412 writeTriplet(visit, "(", " ^^ ", ")");
413 break;
414 case EOpLogicalAnd:
415 writeTriplet(visit, "(", " && ", ")");
416 break;
417 default:
418 UNREACHABLE();
zmo@google.com5601ea02011-06-10 18:23:25 +0000419 }
420
421 return visitChildren;
422}
423
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700424bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000425{
zmo@google.com32e97312011-08-24 01:03:11 +0000426 TString preString;
427 TString postString = ")";
428
zmo@google.com5601ea02011-06-10 18:23:25 +0000429 switch (node->getOp())
430 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700431 case EOpNegative: preString = "(-"; break;
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700432 case EOpPositive: preString = "(+"; break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700433 case EOpVectorLogicalNot: preString = "not("; break;
434 case EOpLogicalNot: preString = "(!"; break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200435 case EOpBitwiseNot: preString = "(~"; break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000436
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700437 case EOpPostIncrement: preString = "("; postString = "++)"; break;
438 case EOpPostDecrement: preString = "("; postString = "--)"; break;
439 case EOpPreIncrement: preString = "(++"; break;
440 case EOpPreDecrement: preString = "(--"; break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000441
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700442 case EOpRadians:
443 preString = "radians(";
444 break;
445 case EOpDegrees:
446 preString = "degrees(";
447 break;
448 case EOpSin:
449 preString = "sin(";
450 break;
451 case EOpCos:
452 preString = "cos(";
453 break;
454 case EOpTan:
455 preString = "tan(";
456 break;
457 case EOpAsin:
458 preString = "asin(";
459 break;
460 case EOpAcos:
461 preString = "acos(";
462 break;
463 case EOpAtan:
464 preString = "atan(";
465 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000466
Olli Etuaho5c9cd3d2014-12-18 13:04:25 +0200467 case EOpSinh:
468 preString = "sinh(";
469 break;
470 case EOpCosh:
471 preString = "cosh(";
472 break;
473 case EOpTanh:
474 preString = "tanh(";
475 break;
476 case EOpAsinh:
477 preString = "asinh(";
478 break;
479 case EOpAcosh:
480 preString = "acosh(";
481 break;
482 case EOpAtanh:
483 preString = "atanh(";
484 break;
485
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700486 case EOpExp:
487 preString = "exp(";
488 break;
489 case EOpLog:
490 preString = "log(";
491 break;
492 case EOpExp2:
493 preString = "exp2(";
494 break;
495 case EOpLog2:
496 preString = "log2(";
497 break;
498 case EOpSqrt:
499 preString = "sqrt(";
500 break;
501 case EOpInverseSqrt:
502 preString = "inversesqrt(";
503 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000504
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700505 case EOpAbs:
506 preString = "abs(";
507 break;
508 case EOpSign:
509 preString = "sign(";
510 break;
511 case EOpFloor:
512 preString = "floor(";
513 break;
514 case EOpCeil:
515 preString = "ceil(";
516 break;
517 case EOpFract:
518 preString = "fract(";
519 break;
Arun Patole0c1726e2015-02-18 14:35:02 +0530520 case EOpIsNan:
521 preString = "isnan(";
522 break;
523 case EOpIsInf:
524 preString = "isinf(";
525 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000526
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200527 case EOpFloatBitsToInt:
528 preString = "floatBitsToInt(";
529 break;
530 case EOpFloatBitsToUint:
531 preString = "floatBitsToUint(";
532 break;
533 case EOpIntBitsToFloat:
534 preString = "intBitsToFloat(";
535 break;
536 case EOpUintBitsToFloat:
537 preString = "uintBitsToFloat(";
538 break;
539
Olli Etuaho7700ff62015-01-15 12:16:29 +0200540 case EOpPackSnorm2x16:
541 preString = "packSnorm2x16(";
542 break;
543 case EOpPackUnorm2x16:
544 preString = "packUnorm2x16(";
545 break;
546 case EOpPackHalf2x16:
547 preString = "packHalf2x16(";
548 break;
549 case EOpUnpackSnorm2x16:
550 preString = "unpackSnorm2x16(";
551 break;
552 case EOpUnpackUnorm2x16:
553 preString = "unpackUnorm2x16(";
554 break;
555 case EOpUnpackHalf2x16:
556 preString = "unpackHalf2x16(";
557 break;
558
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700559 case EOpLength:
560 preString = "length(";
561 break;
562 case EOpNormalize:
563 preString = "normalize(";
564 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000565
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700566 case EOpDFdx:
567 preString = "dFdx(";
568 break;
569 case EOpDFdy:
570 preString = "dFdy(";
571 break;
572 case EOpFwidth:
573 preString = "fwidth(";
574 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000575
Olli Etuahoe39706d2014-12-30 16:40:36 +0200576 case EOpTranspose:
577 preString = "transpose(";
578 break;
579 case EOpDeterminant:
580 preString = "determinant(";
581 break;
Olli Etuahoabf6dad2015-01-14 14:45:16 +0200582 case EOpInverse:
583 preString = "inverse(";
584 break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200585
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700586 case EOpAny:
587 preString = "any(";
588 break;
589 case EOpAll:
590 preString = "all(";
591 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000592
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700593 default:
594 UNREACHABLE();
zmo@google.com5601ea02011-06-10 18:23:25 +0000595 }
596
zmo@google.com32e97312011-08-24 01:03:11 +0000597 if (visit == PreVisit && node->getUseEmulatedFunction())
598 preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
599 writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
600
zmo@google.com5601ea02011-06-10 18:23:25 +0000601 return true;
602}
603
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700604bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000605{
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700606 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +0000607
608 if (node->usesTernaryOperator())
609 {
610 // Notice two brackets at the beginning and end. The outer ones
611 // encapsulate the whole ternary expression. This preserves the
612 // order of precedence when ternary expressions are used in a
613 // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
614 out << "((";
615 node->getCondition()->traverse(this);
616 out << ") ? (";
617 node->getTrueBlock()->traverse(this);
618 out << ") : (";
619 node->getFalseBlock()->traverse(this);
620 out << "))";
621 }
622 else
623 {
624 out << "if (";
625 node->getCondition()->traverse(this);
626 out << ")\n";
627
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700628 incrementDepth(node);
zmo@google.com5601ea02011-06-10 18:23:25 +0000629 visitCodeBlock(node->getTrueBlock());
630
631 if (node->getFalseBlock())
632 {
633 out << "else\n";
634 visitCodeBlock(node->getFalseBlock());
635 }
636 decrementDepth();
637 }
638 return false;
639}
640
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200641bool TOutputGLSLBase::visitSwitch(Visit, TIntermSwitch *)
642{
643 UNIMPLEMENTED();
644 return false;
645}
646
647bool TOutputGLSLBase::visitCase(Visit, TIntermCase *)
648{
649 UNIMPLEMENTED();
650 return false;
651}
652
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700653bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000654{
655 bool visitChildren = true;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700656 TInfoSinkBase &out = objSink();
zmo@google.comf420c422011-09-12 18:27:59 +0000657 TString preString;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700658 bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
zmo@google.com5601ea02011-06-10 18:23:25 +0000659 switch (node->getOp())
660 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700661 case EOpSequence:
662 // Scope the sequences except when at the global scope.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700663 if (mDepth > 0)
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700664 {
665 out << "{\n";
zmo@google.com5601ea02011-06-10 18:23:25 +0000666 }
zmo@google.com5601ea02011-06-10 18:23:25 +0000667
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700668 incrementDepth(node);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700669 for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
670 iter != node->getSequence()->end(); ++iter)
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700671 {
Austin Kinross3ae64652015-01-26 15:51:39 -0800672 TIntermNode *curNode = *iter;
673 ASSERT(curNode != NULL);
674 curNode->traverse(this);
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700675
Austin Kinross3ae64652015-01-26 15:51:39 -0800676 if (isSingleStatement(curNode))
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700677 out << ";\n";
678 }
679 decrementDepth();
680
681 // Scope the sequences except when at the global scope.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700682 if (mDepth > 0)
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700683 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700684 out << "}\n";
685 }
686 visitChildren = false;
687 break;
688 case EOpPrototype:
689 // Function declaration.
690 ASSERT(visit == PreVisit);
691 writeVariableType(node->getType());
Olli Etuaho76acee82014-11-04 13:44:03 +0200692 out << " " << hashFunctionName(node->getName());
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700693
694 out << "(";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700695 writeFunctionParameters(*(node->getSequence()));
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700696 out << ")";
697
698 visitChildren = false;
699 break;
700 case EOpFunction: {
701 // Function definition.
702 ASSERT(visit == PreVisit);
703 writeVariableType(node->getType());
704 out << " " << hashFunctionName(node->getName());
705
706 incrementDepth(node);
707 // Function definition node contains one or two children nodes
708 // representing function parameters and function body. The latter
709 // is not present in case of empty function bodies.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700710 const TIntermSequence &sequence = *(node->getSequence());
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700711 ASSERT((sequence.size() == 1) || (sequence.size() == 2));
712 TIntermSequence::const_iterator seqIter = sequence.begin();
713
714 // Traverse function parameters.
715 TIntermAggregate *params = (*seqIter)->getAsAggregate();
716 ASSERT(params != NULL);
717 ASSERT(params->getOp() == EOpParameters);
718 params->traverse(this);
719
720 // Traverse function body.
721 TIntermAggregate *body = ++seqIter != sequence.end() ?
722 (*seqIter)->getAsAggregate() : NULL;
723 visitCodeBlock(body);
724 decrementDepth();
725
726 // Fully processed; no need to visit children.
727 visitChildren = false;
728 break;
729 }
730 case EOpFunctionCall:
731 // Function call.
732 if (visit == PreVisit)
733 out << hashFunctionName(node->getName()) << "(";
734 else if (visit == InVisit)
735 out << ", ";
736 else
zmo@google.com5601ea02011-06-10 18:23:25 +0000737 out << ")";
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700738 break;
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200739 case EOpInternalFunctionCall:
740 // Function call to an internal helper function.
741 if (visit == PreVisit)
742 out << node->getName() << "(";
743 else if (visit == InVisit)
744 out << ", ";
745 else
746 out << ")";
747 break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700748 case EOpParameters:
749 // Function parameters.
750 ASSERT(visit == PreVisit);
751 out << "(";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700752 writeFunctionParameters(*(node->getSequence()));
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700753 out << ")";
754 visitChildren = false;
755 break;
756 case EOpDeclaration:
757 // Variable declaration.
758 if (visit == PreVisit)
759 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700760 const TIntermSequence &sequence = *(node->getSequence());
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700761 const TIntermTyped *variable = sequence.front()->getAsTyped();
762 writeVariableType(variable->getType());
763 out << " ";
764 mDeclaringVariables = true;
zmo@google.com5601ea02011-06-10 18:23:25 +0000765 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700766 else if (visit == InVisit)
767 {
768 out << ", ";
769 mDeclaringVariables = true;
zmo@google.com5601ea02011-06-10 18:23:25 +0000770 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700771 else
772 {
773 mDeclaringVariables = false;
774 }
775 break;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700776 case EOpInvariantDeclaration:
777 // Invariant declaration.
778 ASSERT(visit == PreVisit);
779 {
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400780 const TIntermSequence *sequence = node->getSequence();
781 ASSERT(sequence && sequence->size() == 1);
782 const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
783 ASSERT(symbol);
Zhenyao Mo2a517272014-10-27 16:09:57 -0700784 out << "invariant " << hashVariableName(symbol->getSymbol());
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400785 }
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700786 visitChildren = false;
787 break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700788 case EOpConstructFloat:
789 writeTriplet(visit, "float(", NULL, ")");
790 break;
791 case EOpConstructVec2:
792 writeBuiltInFunctionTriplet(visit, "vec2(", false);
793 break;
794 case EOpConstructVec3:
795 writeBuiltInFunctionTriplet(visit, "vec3(", false);
796 break;
797 case EOpConstructVec4:
798 writeBuiltInFunctionTriplet(visit, "vec4(", false);
799 break;
800 case EOpConstructBool:
801 writeTriplet(visit, "bool(", NULL, ")");
802 break;
803 case EOpConstructBVec2:
804 writeBuiltInFunctionTriplet(visit, "bvec2(", false);
805 break;
806 case EOpConstructBVec3:
807 writeBuiltInFunctionTriplet(visit, "bvec3(", false);
808 break;
809 case EOpConstructBVec4:
810 writeBuiltInFunctionTriplet(visit, "bvec4(", false);
811 break;
812 case EOpConstructInt:
813 writeTriplet(visit, "int(", NULL, ")");
814 break;
815 case EOpConstructIVec2:
816 writeBuiltInFunctionTriplet(visit, "ivec2(", false);
817 break;
818 case EOpConstructIVec3:
819 writeBuiltInFunctionTriplet(visit, "ivec3(", false);
820 break;
821 case EOpConstructIVec4:
822 writeBuiltInFunctionTriplet(visit, "ivec4(", false);
823 break;
824 case EOpConstructMat2:
825 writeBuiltInFunctionTriplet(visit, "mat2(", false);
826 break;
827 case EOpConstructMat3:
828 writeBuiltInFunctionTriplet(visit, "mat3(", false);
829 break;
830 case EOpConstructMat4:
831 writeBuiltInFunctionTriplet(visit, "mat4(", false);
832 break;
833 case EOpConstructStruct:
834 if (visit == PreVisit)
835 {
836 const TType &type = node->getType();
837 ASSERT(type.getBasicType() == EbtStruct);
838 out << hashName(type.getStruct()->name()) << "(";
839 }
840 else if (visit == InVisit)
841 {
842 out << ", ";
843 }
844 else
845 {
zmo@google.com5601ea02011-06-10 18:23:25 +0000846 out << ")";
zmo@google.com5601ea02011-06-10 18:23:25 +0000847 }
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700848 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000849
Olli Etuahoe39706d2014-12-30 16:40:36 +0200850 case EOpOuterProduct:
851 writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
852 break;
853
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700854 case EOpLessThan:
855 writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
856 break;
857 case EOpGreaterThan:
858 writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction);
859 break;
860 case EOpLessThanEqual:
861 writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction);
862 break;
863 case EOpGreaterThanEqual:
864 writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction);
865 break;
866 case EOpVectorEqual:
867 writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction);
868 break;
869 case EOpVectorNotEqual:
870 writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
871 break;
872 case EOpComma:
Zhenyao Mo0783efd2014-10-21 15:51:59 -0700873 writeTriplet(visit, "(", ", ", ")");
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700874 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000875
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700876 case EOpMod:
877 writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
878 break;
Olli Etuahob6e07a62015-02-16 12:22:10 +0200879 case EOpModf:
880 writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
881 break;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700882 case EOpPow:
883 writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
884 break;
885 case EOpAtan:
886 writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction);
887 break;
888 case EOpMin:
889 writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction);
890 break;
891 case EOpMax:
892 writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction);
893 break;
894 case EOpClamp:
895 writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction);
896 break;
897 case EOpMix:
898 writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction);
899 break;
900 case EOpStep:
901 writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction);
902 break;
903 case EOpSmoothStep:
904 writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction);
905 break;
906 case EOpDistance:
907 writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction);
908 break;
909 case EOpDot:
910 writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction);
911 break;
912 case EOpCross:
913 writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction);
914 break;
915 case EOpFaceForward:
916 writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction);
917 break;
918 case EOpReflect:
919 writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction);
920 break;
921 case EOpRefract:
922 writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction);
923 break;
924 case EOpMul:
925 writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
926 break;
zmo@google.com5601ea02011-06-10 18:23:25 +0000927
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700928 default:
929 UNREACHABLE();
zmo@google.com5601ea02011-06-10 18:23:25 +0000930 }
zmo@google.com5601ea02011-06-10 18:23:25 +0000931 return visitChildren;
932}
933
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700934bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
zmo@google.com5601ea02011-06-10 18:23:25 +0000935{
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700936 TInfoSinkBase &out = objSink();
zmo@google.com5601ea02011-06-10 18:23:25 +0000937
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700938 incrementDepth(node);
zmo@google.com5601ea02011-06-10 18:23:25 +0000939 // Loop header.
940 TLoopType loopType = node->getType();
941 if (loopType == ELoopFor) // for loop
942 {
Zhenyao Mo550c6002014-02-26 15:40:48 -0800943 if (!node->getUnrollFlag())
944 {
zmo@google.com5601ea02011-06-10 18:23:25 +0000945 out << "for (";
946 if (node->getInit())
947 node->getInit()->traverse(this);
948 out << "; ";
949
950 if (node->getCondition())
951 node->getCondition()->traverse(this);
952 out << "; ";
953
954 if (node->getExpression())
955 node->getExpression()->traverse(this);
956 out << ")\n";
957 }
Zhenyao Mo550c6002014-02-26 15:40:48 -0800958 else
959 {
960 // Need to put a one-iteration loop here to handle break.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700961 TIntermSequence *declSeq =
Zhenyao Mo550c6002014-02-26 15:40:48 -0800962 node->getInit()->getAsAggregate()->getSequence();
963 TIntermSymbol *indexSymbol =
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700964 (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
Zhenyao Mo550c6002014-02-26 15:40:48 -0800965 TString name = hashVariableName(indexSymbol->getSymbol());
966 out << "for (int " << name << " = 0; "
967 << name << " < 1; "
968 << "++" << name << ")\n";
969 }
zmo@google.com5601ea02011-06-10 18:23:25 +0000970 }
971 else if (loopType == ELoopWhile) // while loop
972 {
973 out << "while (";
974 ASSERT(node->getCondition() != NULL);
975 node->getCondition()->traverse(this);
976 out << ")\n";
977 }
978 else // do-while loop
979 {
980 ASSERT(loopType == ELoopDoWhile);
981 out << "do\n";
982 }
983
984 // Loop body.
985 if (node->getUnrollFlag())
986 {
Zhenyao Mo550c6002014-02-26 15:40:48 -0800987 out << "{\n";
988 mLoopUnrollStack.push(node);
989 while (mLoopUnrollStack.satisfiesLoopCondition())
zmo@google.com5601ea02011-06-10 18:23:25 +0000990 {
991 visitCodeBlock(node->getBody());
Zhenyao Mo550c6002014-02-26 15:40:48 -0800992 mLoopUnrollStack.step();
zmo@google.com5601ea02011-06-10 18:23:25 +0000993 }
Zhenyao Mo550c6002014-02-26 15:40:48 -0800994 mLoopUnrollStack.pop();
995 out << "}\n";
zmo@google.com5601ea02011-06-10 18:23:25 +0000996 }
997 else
998 {
999 visitCodeBlock(node->getBody());
1000 }
1001
1002 // Loop footer.
1003 if (loopType == ELoopDoWhile) // do-while loop
1004 {
1005 out << "while (";
1006 ASSERT(node->getCondition() != NULL);
1007 node->getCondition()->traverse(this);
1008 out << ");\n";
1009 }
1010 decrementDepth();
1011
1012 // No need to visit children. They have been already processed in
1013 // this function.
1014 return false;
1015}
1016
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001017bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
zmo@google.com5601ea02011-06-10 18:23:25 +00001018{
1019 switch (node->getFlowOp())
1020 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001021 case EOpKill:
1022 writeTriplet(visit, "discard", NULL, NULL);
1023 break;
1024 case EOpBreak:
1025 writeTriplet(visit, "break", NULL, NULL);
1026 break;
1027 case EOpContinue:
1028 writeTriplet(visit, "continue", NULL, NULL);
1029 break;
1030 case EOpReturn:
1031 writeTriplet(visit, "return ", NULL, NULL);
1032 break;
1033 default:
1034 UNREACHABLE();
zmo@google.com5601ea02011-06-10 18:23:25 +00001035 }
1036
1037 return true;
1038}
1039
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001040void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
1041{
zmo@google.com5601ea02011-06-10 18:23:25 +00001042 TInfoSinkBase &out = objSink();
1043 if (node != NULL)
1044 {
1045 node->traverse(this);
1046 // Single statements not part of a sequence need to be terminated
1047 // with semi-colon.
1048 if (isSingleStatement(node))
1049 out << ";\n";
1050 }
1051 else
1052 {
1053 out << "{\n}\n"; // Empty code block.
1054 }
1055}
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001056
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001057TString TOutputGLSLBase::getTypeName(const TType &type)
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001058{
1059 TInfoSinkBase out;
1060 if (type.isMatrix())
1061 {
1062 out << "mat";
1063 out << type.getNominalSize();
1064 }
1065 else if (type.isVector())
1066 {
1067 switch (type.getBasicType())
1068 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001069 case EbtFloat:
1070 out << "vec";
1071 break;
1072 case EbtInt:
1073 out << "ivec";
1074 break;
1075 case EbtBool:
1076 out << "bvec";
1077 break;
1078 default:
1079 UNREACHABLE();
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001080 }
1081 out << type.getNominalSize();
1082 }
1083 else
1084 {
1085 if (type.getBasicType() == EbtStruct)
Jamie Madill98493dd2013-07-08 14:39:03 -04001086 out << hashName(type.getStruct()->name());
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001087 else
1088 out << type.getBasicString();
1089 }
1090 return TString(out.c_str());
1091}
1092
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001093TString TOutputGLSLBase::hashName(const TString &name)
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001094{
1095 if (mHashFunction == NULL || name.empty())
1096 return name;
1097 NameMap::const_iterator it = mNameMap.find(name.c_str());
1098 if (it != mNameMap.end())
1099 return it->second.c_str();
1100 TString hashedName = TIntermTraverser::hash(name, mHashFunction);
1101 mNameMap[name.c_str()] = hashedName.c_str();
1102 return hashedName;
1103}
1104
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001105TString TOutputGLSLBase::hashVariableName(const TString &name)
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001106{
Jamie Madill02f20dd2013-09-12 12:07:42 -04001107 if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL)
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001108 return name;
1109 return hashName(name);
1110}
1111
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001112TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name)
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001113{
1114 TString name = TFunction::unmangleName(mangled_name);
Jamie Madill02f20dd2013-09-12 12:07:42 -04001115 if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main")
Nicolas Capens46485082014-04-15 13:12:50 -04001116 return translateTextureFunction(name);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001117 return hashName(name);
1118}
Jamie Madill98493dd2013-07-08 14:39:03 -04001119
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001120bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
Jamie Madill98493dd2013-07-08 14:39:03 -04001121{
Zhenyao Mo904a9162014-05-09 14:07:45 -07001122 ASSERT(structure);
Jamie Madill01f85ac2014-06-06 11:55:04 -04001123 if (structure->name().empty())
Zhenyao Mo904a9162014-05-09 14:07:45 -07001124 {
Jamie Madill01f85ac2014-06-06 11:55:04 -04001125 return false;
Zhenyao Mo904a9162014-05-09 14:07:45 -07001126 }
Jamie Madill01f85ac2014-06-06 11:55:04 -04001127
1128 return (mDeclaredStructs.count(structure->uniqueId()) > 0);
Jamie Madill98493dd2013-07-08 14:39:03 -04001129}
1130
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001131void TOutputGLSLBase::declareStruct(const TStructure *structure)
Jamie Madill98493dd2013-07-08 14:39:03 -04001132{
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001133 TInfoSinkBase &out = objSink();
Jamie Madill98493dd2013-07-08 14:39:03 -04001134
1135 out << "struct " << hashName(structure->name()) << "{\n";
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001136 const TFieldList &fields = structure->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -04001137 for (size_t i = 0; i < fields.size(); ++i)
1138 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -07001139 const TField *field = fields[i];
Jamie Madill98493dd2013-07-08 14:39:03 -04001140 if (writeVariablePrecision(field->type()->getPrecision()))
1141 out << " ";
1142 out << getTypeName(*field->type()) << " " << hashName(field->name());
1143 if (field->type()->isArray())
1144 out << arrayBrackets(*field->type());
1145 out << ";\n";
1146 }
1147 out << "}";
Zhenyao Mo904a9162014-05-09 14:07:45 -07001148}
Jamie Madill98493dd2013-07-08 14:39:03 -04001149