zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
OutputGLSLBase.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
8 #include "compiler/debug.h"
9 
10 #include <cfloat>
11 
12 namespace
13 {
15 {
16  ASSERT(type.isArray());
17  TInfoSinkBase out;
18  out << "[" << type.getArraySize() << "]";
19  return TString(out.c_str());
20 }
21 
22 bool isSingleStatement(TIntermNode* node) {
23  if (const TIntermAggregate* aggregate = node->getAsAggregate())
24  {
25  return (aggregate->getOp() != EOpFunction) &&
26  (aggregate->getOp() != EOpSequence);
27  }
28  else if (const TIntermSelection* selection = node->getAsSelectionNode())
29  {
30  // Ternary operators are usually part of an assignment operator.
31  // This handles those rare cases in which they are all by themselves.
32  return selection->usesTernaryOperator();
33  }
34  else if (node->getAsLoopNode())
35  {
36  return false;
37  }
38  return true;
39 }
40 } // namespace
41 
43  ShArrayIndexClampingStrategy clampingStrategy,
44  ShHashFunction64 hashFunction,
45  NameMap& nameMap,
46  TSymbolTable& symbolTable)
48  mObjSink(objSink),
49  mDeclaringVariables(false),
50  mClampingStrategy(clampingStrategy),
51  mHashFunction(hashFunction),
52  mNameMap(nameMap),
53  mSymbolTable(symbolTable)
54 {
55 }
56 
57 void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
58 {
59  TInfoSinkBase& out = objSink();
60  if (visit == PreVisit && preStr)
61  {
62  out << preStr;
63  }
64  else if (visit == InVisit && inStr)
65  {
66  out << inStr;
67  }
68  else if (visit == PostVisit && postStr)
69  {
70  out << postStr;
71  }
72 }
73 
75 {
76  TInfoSinkBase& out = objSink();
77  TQualifier qualifier = type.getQualifier();
78  // TODO(alokp): Validate qualifier for variable declarations.
79  if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
80  out << type.getQualifierString() << " ";
81  // Declare the struct if we have not done so already.
82  if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
83  {
84  declareStruct(type.getStruct());
85  }
86  else
87  {
89  out << " ";
90  out << getTypeName(type);
91  }
92 }
93 
95 {
96  TInfoSinkBase& out = objSink();
97  for (TIntermSequence::const_iterator iter = args.begin();
98  iter != args.end(); ++iter)
99  {
100  const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
101  ASSERT(arg != NULL);
102 
103  const TType& type = arg->getType();
104  writeVariableType(type);
105 
106  const TString& name = arg->getSymbol();
107  if (!name.empty())
108  out << " " << hashName(name);
109  if (type.isArray())
110  out << arrayBrackets(type);
111 
112  // Put a comma if this is not the last argument.
113  if (iter != args.end() - 1)
114  out << ", ";
115  }
116 }
117 
119  const ConstantUnion* pConstUnion)
120 {
121  TInfoSinkBase& out = objSink();
122 
123  if (type.getBasicType() == EbtStruct)
124  {
125  const TStructure* structure = type.getStruct();
126  out << hashName(structure->name()) << "(";
127 
128  const TFieldList& fields = structure->fields();
129  for (size_t i = 0; i < fields.size(); ++i)
130  {
131  const TType* fieldType = fields[i]->type();
132  ASSERT(fieldType != NULL);
133  pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
134  if (i != fields.size() - 1) out << ", ";
135  }
136  out << ")";
137  }
138  else
139  {
140  size_t size = type.getObjectSize();
141  bool writeType = size > 1;
142  if (writeType) out << getTypeName(type) << "(";
143  for (size_t i = 0; i < size; ++i, ++pConstUnion)
144  {
145  switch (pConstUnion->getType())
146  {
147  case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break;
148  case EbtInt: out << pConstUnion->getIConst(); break;
149  case EbtBool: out << pConstUnion->getBConst(); break;
150  default: UNREACHABLE();
151  }
152  if (i != size - 1) out << ", ";
153  }
154  if (writeType) out << ")";
155  }
156  return pConstUnion;
157 }
158 
160 {
161  TInfoSinkBase& out = objSink();
162  if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
163  out << mLoopUnroll.GetLoopIndexValue(node);
164  else
165  out << hashVariableName(node->getSymbol());
166 
167  if (mDeclaringVariables && node->getType().isArray())
168  out << arrayBrackets(node->getType());
169 }
170 
172 {
174 }
175 
177 {
178  bool visitChildren = true;
179  TInfoSinkBase& out = objSink();
180  switch (node->getOp())
181  {
182  case EOpInitialize:
183  if (visit == InVisit)
184  {
185  out << " = ";
186  // RHS of initialize is not being declared.
187  mDeclaringVariables = false;
188  }
189  break;
190  case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
191  case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
192  case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
193  case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
194  // Notice the fall-through.
195  case EOpMulAssign:
200  writeTriplet(visit, "(", " *= ", ")");
201  break;
202 
203  case EOpIndexDirect:
204  writeTriplet(visit, NULL, "[", "]");
205  break;
206  case EOpIndexIndirect:
207  if (node->getAddIndexClamp())
208  {
209  if (visit == InVisit)
210  {
211  if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
212  out << "[int(clamp(float(";
213  } else {
214  out << "[webgl_int_clamp(";
215  }
216  }
217  else if (visit == PostVisit)
218  {
219  int maxSize;
220  TIntermTyped *left = node->getLeft();
221  TType leftType = left->getType();
222 
223  if (left->isArray())
224  {
225  // The shader will fail validation if the array length is not > 0.
226  maxSize = leftType.getArraySize() - 1;
227  }
228  else
229  {
230  maxSize = leftType.getNominalSize() - 1;
231  }
232 
233  if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
234  out << "), 0.0, float(" << maxSize << ")))]";
235  } else {
236  out << ", 0, " << maxSize << ")]";
237  }
238  }
239  }
240  else
241  {
242  writeTriplet(visit, NULL, "[", "]");
243  }
244  break;
246  if (visit == InVisit)
247  {
248  // Here we are writing out "foo.bar", where "foo" is struct
249  // and "bar" is field. In AST, it is represented as a binary
250  // node, where left child represents "foo" and right child "bar".
251  // The node itself represents ".". The struct field "bar" is
252  // actually stored as an index into TStructure::fields.
253  out << ".";
254  const TStructure* structure = node->getLeft()->getType().getStruct();
256  const TField* field = structure->fields()[index->getIConst(0)];
257 
258  TString fieldName = field->name();
259  if (!mSymbolTable.findBuiltIn(structure->name()))
260  fieldName = hashName(fieldName);
261 
262  out << fieldName;
263  visitChildren = false;
264  }
265  break;
266  case EOpVectorSwizzle:
267  if (visit == InVisit)
268  {
269  out << ".";
270  TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
271  TIntermSequence& sequence = rightChild->getSequence();
272  for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
273  {
274  TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
275  ASSERT(element->getBasicType() == EbtInt);
276  ASSERT(element->getNominalSize() == 1);
277  const ConstantUnion& data = element->getUnionArrayPointer()[0];
278  ASSERT(data.getType() == EbtInt);
279  switch (data.getIConst())
280  {
281  case 0: out << "x"; break;
282  case 1: out << "y"; break;
283  case 2: out << "z"; break;
284  case 3: out << "w"; break;
285  default: UNREACHABLE(); break;
286  }
287  }
288  visitChildren = false;
289  }
290  break;
291 
292  case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
293  case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
294  case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
295  case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
296  case EOpMod: UNIMPLEMENTED(); break;
297  case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
298  case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
299  case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
300  case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
301  case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
302  case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
303 
304  // Notice the fall-through.
310  writeTriplet(visit, "(", " * ", ")");
311  break;
312 
313  case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
314  case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
315  case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
316  default: UNREACHABLE(); break;
317  }
318 
319  return visitChildren;
320 }
321 
323 {
324  TString preString;
325  TString postString = ")";
326 
327  switch (node->getOp())
328  {
329  case EOpNegative: preString = "(-"; break;
330  case EOpVectorLogicalNot: preString = "not("; break;
331  case EOpLogicalNot: preString = "(!"; break;
332 
333  case EOpPostIncrement: preString = "("; postString = "++)"; break;
334  case EOpPostDecrement: preString = "("; postString = "--)"; break;
335  case EOpPreIncrement: preString = "(++"; break;
336  case EOpPreDecrement: preString = "(--"; break;
337 
338  case EOpConvIntToBool:
339  case EOpConvFloatToBool:
340  switch (node->getOperand()->getType().getNominalSize())
341  {
342  case 1: preString = "bool("; break;
343  case 2: preString = "bvec2("; break;
344  case 3: preString = "bvec3("; break;
345  case 4: preString = "bvec4("; break;
346  default: UNREACHABLE();
347  }
348  break;
349  case EOpConvBoolToFloat:
350  case EOpConvIntToFloat:
351  switch (node->getOperand()->getType().getNominalSize())
352  {
353  case 1: preString = "float("; break;
354  case 2: preString = "vec2("; break;
355  case 3: preString = "vec3("; break;
356  case 4: preString = "vec4("; break;
357  default: UNREACHABLE();
358  }
359  break;
360  case EOpConvFloatToInt:
361  case EOpConvBoolToInt:
362  switch (node->getOperand()->getType().getNominalSize())
363  {
364  case 1: preString = "int("; break;
365  case 2: preString = "ivec2("; break;
366  case 3: preString = "ivec3("; break;
367  case 4: preString = "ivec4("; break;
368  default: UNREACHABLE();
369  }
370  break;
371 
372  case EOpRadians: preString = "radians("; break;
373  case EOpDegrees: preString = "degrees("; break;
374  case EOpSin: preString = "sin("; break;
375  case EOpCos: preString = "cos("; break;
376  case EOpTan: preString = "tan("; break;
377  case EOpAsin: preString = "asin("; break;
378  case EOpAcos: preString = "acos("; break;
379  case EOpAtan: preString = "atan("; break;
380 
381  case EOpExp: preString = "exp("; break;
382  case EOpLog: preString = "log("; break;
383  case EOpExp2: preString = "exp2("; break;
384  case EOpLog2: preString = "log2("; break;
385  case EOpSqrt: preString = "sqrt("; break;
386  case EOpInverseSqrt: preString = "inversesqrt("; break;
387 
388  case EOpAbs: preString = "abs("; break;
389  case EOpSign: preString = "sign("; break;
390  case EOpFloor: preString = "floor("; break;
391  case EOpCeil: preString = "ceil("; break;
392  case EOpFract: preString = "fract("; break;
393 
394  case EOpLength: preString = "length("; break;
395  case EOpNormalize: preString = "normalize("; break;
396 
397  case EOpDFdx: preString = "dFdx("; break;
398  case EOpDFdy: preString = "dFdy("; break;
399  case EOpFwidth: preString = "fwidth("; break;
400 
401  case EOpAny: preString = "any("; break;
402  case EOpAll: preString = "all("; break;
403 
404  default: UNREACHABLE(); break;
405  }
406 
407  if (visit == PreVisit && node->getUseEmulatedFunction())
409  writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
410 
411  return true;
412 }
413 
415 {
416  TInfoSinkBase& out = objSink();
417 
418  if (node->usesTernaryOperator())
419  {
420  // Notice two brackets at the beginning and end. The outer ones
421  // encapsulate the whole ternary expression. This preserves the
422  // order of precedence when ternary expressions are used in a
423  // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
424  out << "((";
425  node->getCondition()->traverse(this);
426  out << ") ? (";
427  node->getTrueBlock()->traverse(this);
428  out << ") : (";
429  node->getFalseBlock()->traverse(this);
430  out << "))";
431  }
432  else
433  {
434  out << "if (";
435  node->getCondition()->traverse(this);
436  out << ")\n";
437 
438  incrementDepth();
439  visitCodeBlock(node->getTrueBlock());
440 
441  if (node->getFalseBlock())
442  {
443  out << "else\n";
444  visitCodeBlock(node->getFalseBlock());
445  }
446  decrementDepth();
447  }
448  return false;
449 }
450 
452 {
453  bool visitChildren = true;
454  TInfoSinkBase& out = objSink();
455  TString preString;
456  bool delayedWrite = false;
457  switch (node->getOp())
458  {
459  case EOpSequence: {
460  // Scope the sequences except when at the global scope.
461  if (depth > 0) out << "{\n";
462 
463  incrementDepth();
464  const TIntermSequence& sequence = node->getSequence();
465  for (TIntermSequence::const_iterator iter = sequence.begin();
466  iter != sequence.end(); ++iter)
467  {
468  TIntermNode* node = *iter;
469  ASSERT(node != NULL);
470  node->traverse(this);
471 
472  if (isSingleStatement(node))
473  out << ";\n";
474  }
475  decrementDepth();
476 
477  // Scope the sequences except when at the global scope.
478  if (depth > 0) out << "}\n";
479  visitChildren = false;
480  break;
481  }
482  case EOpPrototype: {
483  // Function declaration.
484  ASSERT(visit == PreVisit);
485  writeVariableType(node->getType());
486  out << " " << hashName(node->getName());
487 
488  out << "(";
490  out << ")";
491 
492  visitChildren = false;
493  break;
494  }
495  case EOpFunction: {
496  // Function definition.
497  ASSERT(visit == PreVisit);
498  writeVariableType(node->getType());
499  out << " " << hashFunctionName(node->getName());
500 
501  incrementDepth();
502  // Function definition node contains one or two children nodes
503  // representing function parameters and function body. The latter
504  // is not present in case of empty function bodies.
505  const TIntermSequence& sequence = node->getSequence();
506  ASSERT((sequence.size() == 1) || (sequence.size() == 2));
507  TIntermSequence::const_iterator seqIter = sequence.begin();
508 
509  // Traverse function parameters.
510  TIntermAggregate* params = (*seqIter)->getAsAggregate();
511  ASSERT(params != NULL);
512  ASSERT(params->getOp() == EOpParameters);
513  params->traverse(this);
514 
515  // Traverse function body.
516  TIntermAggregate* body = ++seqIter != sequence.end() ?
517  (*seqIter)->getAsAggregate() : NULL;
518  visitCodeBlock(body);
519  decrementDepth();
520 
521  // Fully processed; no need to visit children.
522  visitChildren = false;
523  break;
524  }
525  case EOpFunctionCall:
526  // Function call.
527  if (visit == PreVisit)
528  {
529  out << hashFunctionName(node->getName()) << "(";
530  }
531  else if (visit == InVisit)
532  {
533  out << ", ";
534  }
535  else
536  {
537  out << ")";
538  }
539  break;
540  case EOpParameters: {
541  // Function parameters.
542  ASSERT(visit == PreVisit);
543  out << "(";
545  out << ")";
546  visitChildren = false;
547  break;
548  }
549  case EOpDeclaration: {
550  // Variable declaration.
551  if (visit == PreVisit)
552  {
553  const TIntermSequence& sequence = node->getSequence();
554  const TIntermTyped* variable = sequence.front()->getAsTyped();
555  writeVariableType(variable->getType());
556  out << " ";
557  mDeclaringVariables = true;
558  }
559  else if (visit == InVisit)
560  {
561  out << ", ";
562  mDeclaringVariables = true;
563  }
564  else
565  {
566  mDeclaringVariables = false;
567  }
568  break;
569  }
570  case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
571  case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
572  case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
573  case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
574  case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
575  case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
576  case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
577  case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
578  case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
579  case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
580  case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
581  case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
582  case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
583  case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
584  case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
585  case EOpConstructStruct:
586  if (visit == PreVisit)
587  {
588  const TType& type = node->getType();
589  ASSERT(type.getBasicType() == EbtStruct);
590  out << hashName(type.getStruct()->name()) << "(";
591  }
592  else if (visit == InVisit)
593  {
594  out << ", ";
595  }
596  else
597  {
598  out << ")";
599  }
600  break;
601 
602  case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
603  case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
604  case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
605  case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
606  case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
607  case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
608  case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
609 
610  case EOpMod: preString = "mod("; delayedWrite = true; break;
611  case EOpPow: preString = "pow("; delayedWrite = true; break;
612  case EOpAtan: preString = "atan("; delayedWrite = true; break;
613  case EOpMin: preString = "min("; delayedWrite = true; break;
614  case EOpMax: preString = "max("; delayedWrite = true; break;
615  case EOpClamp: preString = "clamp("; delayedWrite = true; break;
616  case EOpMix: preString = "mix("; delayedWrite = true; break;
617  case EOpStep: preString = "step("; delayedWrite = true; break;
618  case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
619 
620  case EOpDistance: preString = "distance("; delayedWrite = true; break;
621  case EOpDot: preString = "dot("; delayedWrite = true; break;
622  case EOpCross: preString = "cross("; delayedWrite = true; break;
623  case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
624  case EOpReflect: preString = "reflect("; delayedWrite = true; break;
625  case EOpRefract: preString = "refract("; delayedWrite = true; break;
626  case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
627 
628  default: UNREACHABLE(); break;
629  }
630  if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
632  if (delayedWrite)
633  writeTriplet(visit, preString.c_str(), ", ", ")");
634  return visitChildren;
635 }
636 
638 {
639  TInfoSinkBase& out = objSink();
640 
641  incrementDepth();
642  // Loop header.
643  TLoopType loopType = node->getType();
644  if (loopType == ELoopFor) // for loop
645  {
646  if (!node->getUnrollFlag()) {
647  out << "for (";
648  if (node->getInit())
649  node->getInit()->traverse(this);
650  out << "; ";
651 
652  if (node->getCondition())
653  node->getCondition()->traverse(this);
654  out << "; ";
655 
656  if (node->getExpression())
657  node->getExpression()->traverse(this);
658  out << ")\n";
659  }
660  }
661  else if (loopType == ELoopWhile) // while loop
662  {
663  out << "while (";
664  ASSERT(node->getCondition() != NULL);
665  node->getCondition()->traverse(this);
666  out << ")\n";
667  }
668  else // do-while loop
669  {
670  ASSERT(loopType == ELoopDoWhile);
671  out << "do\n";
672  }
673 
674  // Loop body.
675  if (node->getUnrollFlag())
676  {
677  TLoopIndexInfo indexInfo;
678  mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
679  mLoopUnroll.Push(indexInfo);
680  while (mLoopUnroll.SatisfiesLoopCondition())
681  {
682  visitCodeBlock(node->getBody());
683  mLoopUnroll.Step();
684  }
685  mLoopUnroll.Pop();
686  }
687  else
688  {
689  visitCodeBlock(node->getBody());
690  }
691 
692  // Loop footer.
693  if (loopType == ELoopDoWhile) // do-while loop
694  {
695  out << "while (";
696  ASSERT(node->getCondition() != NULL);
697  node->getCondition()->traverse(this);
698  out << ");\n";
699  }
700  decrementDepth();
701 
702  // No need to visit children. They have been already processed in
703  // this function.
704  return false;
705 }
706 
708 {
709  switch (node->getFlowOp())
710  {
711  case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
712  case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
713  case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
714  case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
715  default: UNREACHABLE(); break;
716  }
717 
718  return true;
719 }
720 
722  TInfoSinkBase &out = objSink();
723  if (node != NULL)
724  {
725  node->traverse(this);
726  // Single statements not part of a sequence need to be terminated
727  // with semi-colon.
728  if (isSingleStatement(node))
729  out << ";\n";
730  }
731  else
732  {
733  out << "{\n}\n"; // Empty code block.
734  }
735 }
736 
738 {
739  TInfoSinkBase out;
740  if (type.isMatrix())
741  {
742  out << "mat";
743  out << type.getNominalSize();
744  }
745  else if (type.isVector())
746  {
747  switch (type.getBasicType())
748  {
749  case EbtFloat: out << "vec"; break;
750  case EbtInt: out << "ivec"; break;
751  case EbtBool: out << "bvec"; break;
752  default: UNREACHABLE(); break;
753  }
754  out << type.getNominalSize();
755  }
756  else
757  {
758  if (type.getBasicType() == EbtStruct)
759  out << hashName(type.getStruct()->name());
760  else
761  out << type.getBasicString();
762  }
763  return TString(out.c_str());
764 }
765 
767 {
768  if (mHashFunction == NULL || name.empty())
769  return name;
770  NameMap::const_iterator it = mNameMap.find(name.c_str());
771  if (it != mNameMap.end())
772  return it->second.c_str();
773  TString hashedName = TIntermTraverser::hash(name, mHashFunction);
774  mNameMap[name.c_str()] = hashedName.c_str();
775  return hashedName;
776 }
777 
779 {
780  if (mSymbolTable.findBuiltIn(name) != NULL)
781  return name;
782  return hashName(name);
783 }
784 
786 {
787  TString name = TFunction::unmangleName(mangled_name);
788  if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main")
789  return name;
790  return hashName(name);
791 }
792 
793 bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
794 {
795  return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
796 }
797 
798 void TOutputGLSLBase::declareStruct(const TStructure* structure)
799 {
800  TInfoSinkBase& out = objSink();
801 
802  out << "struct " << hashName(structure->name()) << "{\n";
803  const TFieldList& fields = structure->fields();
804  for (size_t i = 0; i < fields.size(); ++i)
805  {
806  const TField* field = fields[i];
807  if (writeVariablePrecision(field->type()->getPrecision()))
808  out << " ";
809  out << getTypeName(*field->type()) << " " << hashName(field->name());
810  if (field->type()->isArray())
811  out << arrayBrackets(*field->type());
812  out << ";\n";
813  }
814  out << "}";
815 
816  mDeclaredStructs.insert(structure->name());
817 }
TInfoSinkBase & objSink()
void writeVariableType(const TType &type)
Visit
Definition: intermediate.h:524
TOperator getOp() const
Definition: intermediate.h:389
TQualifier
Definition: BaseTypes.h:81
bool getBConst()
Definition: ConstantUnion.h:27
TIntermSequence & getSequence()
Definition: intermediate.h:469
TIntermNode * getTrueBlock() const
Definition: intermediate.h:514
Definition: Types.h:19
TIntermTyped * getCondition()
Definition: intermediate.h:301
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
bool getUnrollFlag()
Definition: intermediate.h:306
GLint left
Definition: glew.h:7291
TOutputGLSLBase(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable)
TIntermTyped * getLeft() const
Definition: intermediate.h:413
#define NULL
Definition: ftobjs.h:61
virtual TIntermAggregate * getAsAggregate()
Definition: intermediate.h:223
virtual TIntermSymbol * getAsSymbolNode()
Definition: intermediate.h:357
khronos_uint64_t(* ShHashFunction64)(const char *, size_t)
Definition: ShaderLang.h:197
const TString & name() const
Definition: Types.h:56
TString hashVariableName(const TString &name)
TOperator getFlowOp()
Definition: intermediate.h:329
TIntermNode * getFalseBlock() const
Definition: intermediate.h:515
TIntermTyped * getRight() const
Definition: intermediate.h:414
const char * getQualifierString() const
Definition: Types.h:211
std::map< TPersistString, TPersistString > NameMap
Definition: HashNames.h:17
virtual bool visitSelection(Visit visit, TIntermSelection *node)
TBasicType getBasicType() const
Definition: intermediate.h:254
virtual TIntermConstantUnion * getAsConstantUnion()
Definition: intermediate.h:375
TBasicType getBasicType() const
Definition: Types.h:108
int getNominalSize() const
Definition: Types.h:118
EGLImageKHR EGLint * name
Definition: eglext.h:284
const TString & name() const
Definition: Types.h:30
GLenum GLenum variable
Definition: glew.h:12631
TString hashFunctionName(const TString &mangled_name)
Definition: Types.h:93
virtual bool visitAggregate(Visit visit, TIntermAggregate *node)
GLenum GLvoid ** params
Definition: gl2ext.h:806
bool isArray() const
Definition: Types.h:162
ShArrayIndexClampingStrategy
Definition: ShaderLang.h:175
bool getUseEmulatedFunction()
Definition: intermediate.h:444
TString getTypeName(const TType &type)
void FillLoopIndexInfo(TIntermLoop *node, TLoopIndexInfo &info)
virtual TIntermConstantUnion * getAsConstantUnion()
Definition: intermediate.h:222
TPrecision getPrecision() const
Definition: Types.h:111
static TString GetEmulatedFunctionName(const TString &name)
virtual void visitConstantUnion(TIntermConstantUnion *node)
TType * type()
Definition: Types.h:27
TSymbol * findBuiltIn(const TString &name)
Definition: SymbolTable.h:327
void visitCodeBlock(TIntermNode *node)
#define ASSERT(expression)
Definition: debug.h:36
TQualifier getQualifier() const
Definition: Types.h:114
int GetLoopIndexValue(TIntermSymbol *symbol)
float getFConst()
Definition: ConstantUnion.h:26
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define true
Definition: ftrandom.c:49
bool getUseEmulatedFunction()
Definition: intermediate.h:483
virtual void traverse(TIntermTraverser *)=0
TIntermNode * getCondition() const
Definition: intermediate.h:513
const TType & getType() const
Definition: intermediate.h:251
static TString hash(const TString &name, ShHashFunction64 hashFunction)
TIntermNode * getBody()
Definition: intermediate.h:303
ConstantUnion * getUnionArrayPointer() const
Definition: intermediate.h:369
TBasicType getType() const
const TString & getName() const
Definition: intermediate.h:472
#define UNREACHABLE()
Definition: debug.h:47
TString hashName(const TString &name)
GLint GLenum GLsizei GLsizei GLsizei depth
Definition: gl2ext.h:845
GLuint index
Definition: glew.h:1800
bool isVector() const
Definition: Types.h:167
static TString arrayBrackets(int index)
Definition: VariableInfo.cpp:9
TIntermTyped * getOperand()
Definition: intermediate.h:440
virtual void visitSymbol(TIntermSymbol *node)
void writeFunctionParameters(const TIntermSequence &args)
virtual bool visitLoop(Visit visit, TIntermLoop *node)
virtual TIntermLoop * getAsLoopNode()
Definition: intermediate.h:228
virtual void traverse(TIntermTraverser *)
int getIConst(int index) const
Definition: intermediate.h:371
std::basic_string< char, std::char_traits< char >, TStringAllocator > TString
Definition: Common.h:41
bool usesTernaryOperator() const
Definition: intermediate.h:512
static TString unmangleName(const TString &mangledName)
Definition: SymbolTable.h:146
virtual bool visitBranch(Visit visit, TIntermBranch *node)
void Push(TLoopIndexInfo &info)
void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr)
virtual bool visitBinary(Visit visit, TIntermBinary *node)
bool isArray() const
Definition: intermediate.h:260
int getArraySize() const
Definition: Types.h:163
TIntermTyped * getExpression()
Definition: intermediate.h:302
bool getAddIndexClamp()
Definition: intermediate.h:418
bool isMatrix() const
Definition: Types.h:159
virtual bool writeVariablePrecision(TPrecision precision)=0
size_t getObjectSize() const
Definition: SymbolTable.cpp:61
const char * getBasicString() const
Definition: Types.h:209
const TFieldList & fields() const
Definition: Types.h:57
TStructure * getStruct() const
Definition: Types.h:170
const TString & getSymbol() const
Definition: intermediate.h:349
#define min(x, y)
Definition: os.h:75
TLoopType
Definition: intermediate.h:278
int i
Definition: pngrutil.c:1377
const char * c_str() const
Definition: InfoSink.h:97
bool SatisfiesLoopCondition()
TIntermNode * getInit()
Definition: intermediate.h:300
#define max(x, y)
Definition: os.h:79
int getNominalSize() const
Definition: intermediate.h:257
const ConstantUnion * writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion)
#define UNIMPLEMENTED()
Definition: debug.h:42
#define false
Definition: ftrandom.c:50
bool NeedsToReplaceSymbolWithValue(TIntermSymbol *symbol)
virtual TIntermSelection * getAsSelectionNode()
Definition: intermediate.h:226
virtual TIntermAggregate * getAsAggregate()
Definition: intermediate.h:466
virtual bool visitUnary(Visit visit, TIntermUnary *node)
GLsizei size
Definition: gl2ext.h:1467
TLoopType getType() const
Definition: intermediate.h:299