LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - OutputGLSLBase.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 731 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2014 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             : 
       7             : #include "compiler/translator/OutputGLSLBase.h"
       8             : 
       9             : #include "common/debug.h"
      10             : #include "common/mathutil.h"
      11             : 
      12             : #include <cfloat>
      13             : 
      14             : namespace sh
      15             : {
      16             : 
      17             : namespace
      18             : {
      19           0 : TString arrayBrackets(const TType &type)
      20             : {
      21           0 :     ASSERT(type.isArray());
      22           0 :     TInfoSinkBase out;
      23           0 :     out << "[" << type.getArraySize() << "]";
      24           0 :     return TString(out.c_str());
      25             : }
      26             : 
      27           0 : bool isSingleStatement(TIntermNode *node)
      28             : {
      29           0 :     if (node->getAsFunctionDefinition())
      30             :     {
      31           0 :         return false;
      32             :     }
      33           0 :     else if (node->getAsBlock())
      34             :     {
      35           0 :         return false;
      36             :     }
      37           0 :     else if (node->getAsIfElseNode())
      38             :     {
      39           0 :         return false;
      40             :     }
      41           0 :     else if (node->getAsLoopNode())
      42             :     {
      43           0 :         return false;
      44             :     }
      45           0 :     else if (node->getAsSwitchNode())
      46             :     {
      47           0 :         return false;
      48             :     }
      49           0 :     else if (node->getAsCaseNode())
      50             :     {
      51           0 :         return false;
      52             :     }
      53           0 :     return true;
      54             : }
      55             : 
      56             : // If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever
      57             : // variables with specified layout qualifiers are copied. Additional checks are needed against the
      58             : // type and storage qualifier of the variable to verify that layout qualifiers have to be outputted.
      59             : // TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove
      60             : // NeedsToWriteLayoutQualifier.
      61           0 : bool NeedsToWriteLayoutQualifier(const TType &type)
      62             : {
      63           0 :     if (type.getBasicType() == EbtInterfaceBlock)
      64             :     {
      65           0 :         return false;
      66             :     }
      67             : 
      68           0 :     const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
      69             : 
      70           0 :     if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) &&
      71           0 :         layoutQualifier.location >= 0)
      72             :     {
      73           0 :         return true;
      74             :     }
      75           0 :     if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
      76             :     {
      77           0 :         return true;
      78             :     }
      79           0 :     return false;
      80             : }
      81             : 
      82             : }  // namespace
      83             : 
      84           0 : TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
      85             :                                  ShArrayIndexClampingStrategy clampingStrategy,
      86             :                                  ShHashFunction64 hashFunction,
      87             :                                  NameMap &nameMap,
      88             :                                  TSymbolTable &symbolTable,
      89             :                                  sh::GLenum shaderType,
      90             :                                  int shaderVersion,
      91             :                                  ShShaderOutput output,
      92           0 :                                  ShCompileOptions compileOptions)
      93             :     : TIntermTraverser(true, true, true),
      94             :       mObjSink(objSink),
      95             :       mDeclaringVariables(false),
      96             :       mClampingStrategy(clampingStrategy),
      97             :       mHashFunction(hashFunction),
      98             :       mNameMap(nameMap),
      99             :       mSymbolTable(symbolTable),
     100             :       mShaderType(shaderType),
     101             :       mShaderVersion(shaderVersion),
     102             :       mOutput(output),
     103           0 :       mCompileOptions(compileOptions)
     104             : {
     105           0 : }
     106             : 
     107           0 : void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
     108             : {
     109           0 :     if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
     110             :     {
     111           0 :         TInfoSinkBase &out = objSink();
     112           0 :         out << "invariant ";
     113             :     }
     114           0 : }
     115             : 
     116           0 : void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
     117             : {
     118           0 :     if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
     119             :     {
     120           0 :         out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(f) << "u)";
     121             :     }
     122             :     else
     123             :     {
     124           0 :         out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
     125             :     }
     126           0 : }
     127             : 
     128           0 : void TOutputGLSLBase::writeTriplet(
     129             :     Visit visit, const char *preStr, const char *inStr, const char *postStr)
     130             : {
     131           0 :     TInfoSinkBase &out = objSink();
     132           0 :     if (visit == PreVisit && preStr)
     133           0 :         out << preStr;
     134           0 :     else if (visit == InVisit && inStr)
     135           0 :         out << inStr;
     136           0 :     else if (visit == PostVisit && postStr)
     137           0 :         out << postStr;
     138           0 : }
     139             : 
     140           0 : void TOutputGLSLBase::writeBuiltInFunctionTriplet(
     141             :     Visit visit, const char *preStr, bool useEmulatedFunction)
     142             : {
     143             :     TString preString = useEmulatedFunction ?
     144           0 :         BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr;
     145           0 :     writeTriplet(visit, preString.c_str(), ", ", ")");
     146           0 : }
     147             : 
     148           0 : void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
     149             : {
     150           0 :     if (!NeedsToWriteLayoutQualifier(type))
     151             :     {
     152           0 :         return;
     153             :     }
     154             : 
     155           0 :     TInfoSinkBase &out                      = objSink();
     156           0 :     const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
     157           0 :     out << "layout(";
     158             : 
     159           0 :     if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn)
     160             :     {
     161           0 :         if (layoutQualifier.location >= 0)
     162             :         {
     163           0 :             out << "location = " << layoutQualifier.location;
     164             :         }
     165             :     }
     166             : 
     167           0 :     if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
     168             :     {
     169           0 :         ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
     170           0 :         out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
     171             :     }
     172             : 
     173           0 :     out << ") ";
     174             : }
     175             : 
     176           0 : const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
     177             : {
     178           0 :     if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
     179           0 :         (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
     180             :     {
     181           0 :         switch (qualifier)
     182             :         {
     183             :             // The return string is consistent with sh::getQualifierString() from
     184             :             // BaseTypes.h minus the "centroid" keyword.
     185             :             case EvqCentroid:
     186           0 :                 return "";
     187             :             case EvqCentroidIn:
     188           0 :                 return "smooth in";
     189             :             case EvqCentroidOut:
     190           0 :                 return "smooth out";
     191             :             default:
     192           0 :                 break;
     193             :         }
     194             :     }
     195           0 :     if (sh::IsGLSL130OrNewer(mOutput))
     196             :     {
     197           0 :         switch (qualifier)
     198             :         {
     199             :             case EvqAttribute:
     200           0 :                 return "in";
     201             :             case EvqVaryingIn:
     202           0 :                 return "in";
     203             :             case EvqVaryingOut:
     204           0 :                 return "out";
     205             :             default:
     206           0 :                 break;
     207             :         }
     208             :     }
     209           0 :     return sh::getQualifierString(qualifier);
     210             : }
     211             : 
     212           0 : void TOutputGLSLBase::writeVariableType(const TType &type)
     213             : {
     214           0 :     TQualifier qualifier = type.getQualifier();
     215           0 :     TInfoSinkBase &out = objSink();
     216           0 :     if (type.isInvariant())
     217             :     {
     218           0 :         writeInvariantQualifier(type);
     219             :     }
     220           0 :     if (type.getBasicType() == EbtInterfaceBlock)
     221             :     {
     222           0 :         TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
     223           0 :         declareInterfaceBlockLayout(interfaceBlock);
     224             :     }
     225           0 :     if (qualifier != EvqTemporary && qualifier != EvqGlobal)
     226             :     {
     227           0 :         const char *qualifierString = mapQualifierToString(qualifier);
     228           0 :         if (qualifierString && qualifierString[0] != '\0')
     229             :         {
     230           0 :             out << qualifierString << " ";
     231             :         }
     232             :     }
     233             : 
     234           0 :     const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
     235           0 :     if (memoryQualifier.readonly)
     236             :     {
     237           0 :         ASSERT(IsImage(type.getBasicType()));
     238           0 :         out << "readonly ";
     239             :     }
     240             : 
     241           0 :     if (memoryQualifier.writeonly)
     242             :     {
     243           0 :         ASSERT(IsImage(type.getBasicType()));
     244           0 :         out << "writeonly ";
     245             :     }
     246             : 
     247           0 :     if (memoryQualifier.coherent)
     248             :     {
     249           0 :         ASSERT(IsImage(type.getBasicType()));
     250           0 :         out << "coherent ";
     251             :     }
     252             : 
     253           0 :     if (memoryQualifier.restrictQualifier)
     254             :     {
     255           0 :         ASSERT(IsImage(type.getBasicType()));
     256           0 :         out << "restrict ";
     257             :     }
     258             : 
     259           0 :     if (memoryQualifier.volatileQualifier)
     260             :     {
     261           0 :         ASSERT(IsImage(type.getBasicType()));
     262           0 :         out << "volatile ";
     263             :     }
     264             : 
     265             :     // Declare the struct if we have not done so already.
     266           0 :     if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
     267             :     {
     268           0 :         TStructure *structure = type.getStruct();
     269             : 
     270           0 :         declareStruct(structure);
     271             : 
     272           0 :         if (!structure->name().empty())
     273             :         {
     274           0 :             mDeclaredStructs.insert(structure->uniqueId());
     275             :         }
     276             :     }
     277           0 :     else if (type.getBasicType() == EbtInterfaceBlock)
     278             :     {
     279           0 :         TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
     280           0 :         declareInterfaceBlock(interfaceBlock);
     281             :     }
     282             :     else
     283             :     {
     284           0 :         if (writeVariablePrecision(type.getPrecision()))
     285           0 :             out << " ";
     286           0 :         out << getTypeName(type);
     287             :     }
     288           0 : }
     289             : 
     290           0 : void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
     291             : {
     292           0 :     TInfoSinkBase &out = objSink();
     293           0 :     for (TIntermSequence::const_iterator iter = args.begin();
     294           0 :          iter != args.end(); ++iter)
     295             :     {
     296           0 :         const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
     297           0 :         ASSERT(arg != NULL);
     298             : 
     299           0 :         const TType &type = arg->getType();
     300           0 :         writeVariableType(type);
     301             : 
     302           0 :         if (!arg->getName().getString().empty())
     303           0 :             out << " " << hashName(arg->getName());
     304           0 :         if (type.isArray())
     305           0 :             out << arrayBrackets(type);
     306             : 
     307             :         // Put a comma if this is not the last argument.
     308           0 :         if (iter != args.end() - 1)
     309           0 :             out << ", ";
     310             :     }
     311           0 : }
     312             : 
     313           0 : const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
     314             :     const TType &type, const TConstantUnion *pConstUnion)
     315             : {
     316           0 :     TInfoSinkBase &out = objSink();
     317             : 
     318           0 :     if (type.getBasicType() == EbtStruct)
     319             :     {
     320           0 :         const TStructure *structure = type.getStruct();
     321           0 :         out << hashName(TName(structure->name())) << "(";
     322             : 
     323           0 :         const TFieldList &fields = structure->fields();
     324           0 :         for (size_t i = 0; i < fields.size(); ++i)
     325             :         {
     326           0 :             const TType *fieldType = fields[i]->type();
     327           0 :             ASSERT(fieldType != NULL);
     328           0 :             pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
     329           0 :             if (i != fields.size() - 1)
     330           0 :                 out << ", ";
     331             :         }
     332           0 :         out << ")";
     333             :     }
     334             :     else
     335             :     {
     336           0 :         size_t size = type.getObjectSize();
     337           0 :         bool writeType = size > 1;
     338           0 :         if (writeType)
     339           0 :             out << getTypeName(type) << "(";
     340           0 :         for (size_t i = 0; i < size; ++i, ++pConstUnion)
     341             :         {
     342           0 :             switch (pConstUnion->getType())
     343             :             {
     344             :               case EbtFloat:
     345           0 :                   writeFloat(out, pConstUnion->getFConst());
     346           0 :                   break;
     347             :               case EbtInt:
     348           0 :                 out << pConstUnion->getIConst();
     349           0 :                 break;
     350             :               case EbtUInt:
     351           0 :                 out << pConstUnion->getUConst() << "u";
     352           0 :                 break;
     353             :               case EbtBool:
     354           0 :                 out << pConstUnion->getBConst();
     355           0 :                 break;
     356           0 :               default: UNREACHABLE();
     357             :             }
     358           0 :             if (i != size - 1)
     359           0 :                 out << ", ";
     360             :         }
     361           0 :         if (writeType)
     362           0 :             out << ")";
     363             :     }
     364           0 :     return pConstUnion;
     365             : }
     366             : 
     367           0 : void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
     368             : {
     369           0 :     TInfoSinkBase &out = objSink();
     370           0 :     if (visit == PreVisit)
     371             :     {
     372           0 :         if (type.isArray())
     373             :         {
     374           0 :             out << getTypeName(type);
     375           0 :             out << arrayBrackets(type);
     376           0 :             out << "(";
     377             :         }
     378             :         else
     379             :         {
     380           0 :             out << getTypeName(type) << "(";
     381             :         }
     382             :     }
     383             :     else
     384             :     {
     385           0 :         writeTriplet(visit, nullptr, ", ", ")");
     386             :     }
     387           0 : }
     388             : 
     389           0 : void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
     390             : {
     391           0 :     TInfoSinkBase &out = objSink();
     392           0 :     out << hashVariableName(node->getName());
     393             : 
     394           0 :     if (mDeclaringVariables && node->getType().isArray())
     395           0 :         out << arrayBrackets(node->getType());
     396           0 : }
     397             : 
     398           0 : void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
     399             : {
     400           0 :     writeConstantUnion(node->getType(), node->getUnionArrayPointer());
     401           0 : }
     402             : 
     403           0 : bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node)
     404             : {
     405           0 :     TInfoSinkBase &out = objSink();
     406           0 :     if (visit == PostVisit)
     407             :     {
     408           0 :         out << ".";
     409           0 :         node->writeOffsetsAsXYZW(&out);
     410             :     }
     411           0 :     return true;
     412             : }
     413             : 
     414           0 : bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
     415             : {
     416           0 :     bool visitChildren = true;
     417           0 :     TInfoSinkBase &out = objSink();
     418           0 :     switch (node->getOp())
     419             :     {
     420             :         case EOpComma:
     421           0 :             writeTriplet(visit, "(", ", ", ")");
     422           0 :             break;
     423             :         case EOpInitialize:
     424           0 :             if (visit == InVisit)
     425             :             {
     426           0 :                 out << " = ";
     427             :                 // RHS of initialize is not being declared.
     428           0 :                 mDeclaringVariables = false;
     429             :             }
     430           0 :             break;
     431             :         case EOpAssign:
     432           0 :             writeTriplet(visit, "(", " = ", ")");
     433           0 :             break;
     434             :         case EOpAddAssign:
     435           0 :             writeTriplet(visit, "(", " += ", ")");
     436           0 :             break;
     437             :         case EOpSubAssign:
     438           0 :             writeTriplet(visit, "(", " -= ", ")");
     439           0 :             break;
     440             :         case EOpDivAssign:
     441           0 :             writeTriplet(visit, "(", " /= ", ")");
     442           0 :             break;
     443             :         case EOpIModAssign:
     444           0 :             writeTriplet(visit, "(", " %= ", ")");
     445           0 :             break;
     446             :         // Notice the fall-through.
     447             :         case EOpMulAssign:
     448             :         case EOpVectorTimesMatrixAssign:
     449             :         case EOpVectorTimesScalarAssign:
     450             :         case EOpMatrixTimesScalarAssign:
     451             :         case EOpMatrixTimesMatrixAssign:
     452           0 :             writeTriplet(visit, "(", " *= ", ")");
     453           0 :             break;
     454             :         case EOpBitShiftLeftAssign:
     455           0 :             writeTriplet(visit, "(", " <<= ", ")");
     456           0 :             break;
     457             :         case EOpBitShiftRightAssign:
     458           0 :             writeTriplet(visit, "(", " >>= ", ")");
     459           0 :             break;
     460             :         case EOpBitwiseAndAssign:
     461           0 :             writeTriplet(visit, "(", " &= ", ")");
     462           0 :             break;
     463             :         case EOpBitwiseXorAssign:
     464           0 :             writeTriplet(visit, "(", " ^= ", ")");
     465           0 :             break;
     466             :         case EOpBitwiseOrAssign:
     467           0 :             writeTriplet(visit, "(", " |= ", ")");
     468           0 :             break;
     469             : 
     470             :         case EOpIndexDirect:
     471           0 :             writeTriplet(visit, NULL, "[", "]");
     472           0 :             break;
     473             :         case EOpIndexIndirect:
     474           0 :             if (node->getAddIndexClamp())
     475             :             {
     476           0 :                 if (visit == InVisit)
     477             :                 {
     478           0 :                     if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
     479           0 :                         out << "[int(clamp(float(";
     480             :                     else
     481           0 :                         out << "[webgl_int_clamp(";
     482             :                 }
     483           0 :                 else if (visit == PostVisit)
     484             :                 {
     485             :                     int maxSize;
     486           0 :                     TIntermTyped *left = node->getLeft();
     487           0 :                     TType leftType     = left->getType();
     488             : 
     489           0 :                     if (left->isArray())
     490             :                     {
     491             :                         // The shader will fail validation if the array length is not > 0.
     492           0 :                         maxSize = static_cast<int>(leftType.getArraySize()) - 1;
     493             :                     }
     494             :                     else
     495             :                     {
     496           0 :                         maxSize = leftType.getNominalSize() - 1;
     497             :                     }
     498             : 
     499           0 :                     if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
     500           0 :                         out << "), 0.0, float(" << maxSize << ")))]";
     501             :                     else
     502           0 :                         out << ", 0, " << maxSize << ")]";
     503             :                 }
     504             :             }
     505             :             else
     506             :             {
     507           0 :                 writeTriplet(visit, NULL, "[", "]");
     508             :             }
     509           0 :             break;
     510             :         case EOpIndexDirectStruct:
     511           0 :             if (visit == InVisit)
     512             :             {
     513             :                 // Here we are writing out "foo.bar", where "foo" is struct
     514             :                 // and "bar" is field. In AST, it is represented as a binary
     515             :                 // node, where left child represents "foo" and right child "bar".
     516             :                 // The node itself represents ".". The struct field "bar" is
     517             :                 // actually stored as an index into TStructure::fields.
     518           0 :                 out << ".";
     519           0 :                 const TStructure *structure       = node->getLeft()->getType().getStruct();
     520           0 :                 const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
     521           0 :                 const TField *field               = structure->fields()[index->getIConst(0)];
     522             : 
     523           0 :                 TString fieldName = field->name();
     524           0 :                 if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
     525           0 :                     fieldName = hashName(TName(fieldName));
     526             : 
     527           0 :                 out << fieldName;
     528           0 :                 visitChildren = false;
     529             :             }
     530           0 :             break;
     531             :         case EOpIndexDirectInterfaceBlock:
     532           0 :             if (visit == InVisit)
     533             :             {
     534           0 :                 out << ".";
     535             :                 const TInterfaceBlock *interfaceBlock =
     536           0 :                     node->getLeft()->getType().getInterfaceBlock();
     537           0 :                 const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
     538           0 :                 const TField *field               = interfaceBlock->fields()[index->getIConst(0)];
     539             : 
     540           0 :                 TString fieldName = field->name();
     541           0 :                 ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
     542           0 :                 fieldName = hashName(TName(fieldName));
     543             : 
     544           0 :                 out << fieldName;
     545           0 :                 visitChildren = false;
     546             :             }
     547           0 :             break;
     548             : 
     549             :         case EOpAdd:
     550           0 :             writeTriplet(visit, "(", " + ", ")");
     551           0 :             break;
     552             :         case EOpSub:
     553           0 :             writeTriplet(visit, "(", " - ", ")");
     554           0 :             break;
     555             :         case EOpMul:
     556           0 :             writeTriplet(visit, "(", " * ", ")");
     557           0 :             break;
     558             :         case EOpDiv:
     559           0 :             writeTriplet(visit, "(", " / ", ")");
     560           0 :             break;
     561             :         case EOpIMod:
     562           0 :             writeTriplet(visit, "(", " % ", ")");
     563           0 :             break;
     564             :         case EOpBitShiftLeft:
     565           0 :             writeTriplet(visit, "(", " << ", ")");
     566           0 :             break;
     567             :         case EOpBitShiftRight:
     568           0 :             writeTriplet(visit, "(", " >> ", ")");
     569           0 :             break;
     570             :         case EOpBitwiseAnd:
     571           0 :             writeTriplet(visit, "(", " & ", ")");
     572           0 :             break;
     573             :         case EOpBitwiseXor:
     574           0 :             writeTriplet(visit, "(", " ^ ", ")");
     575           0 :             break;
     576             :         case EOpBitwiseOr:
     577           0 :             writeTriplet(visit, "(", " | ", ")");
     578           0 :             break;
     579             : 
     580             :         case EOpEqual:
     581           0 :             writeTriplet(visit, "(", " == ", ")");
     582           0 :             break;
     583             :         case EOpNotEqual:
     584           0 :             writeTriplet(visit, "(", " != ", ")");
     585           0 :             break;
     586             :         case EOpLessThan:
     587           0 :             writeTriplet(visit, "(", " < ", ")");
     588           0 :             break;
     589             :         case EOpGreaterThan:
     590           0 :             writeTriplet(visit, "(", " > ", ")");
     591           0 :             break;
     592             :         case EOpLessThanEqual:
     593           0 :             writeTriplet(visit, "(", " <= ", ")");
     594           0 :             break;
     595             :         case EOpGreaterThanEqual:
     596           0 :             writeTriplet(visit, "(", " >= ", ")");
     597           0 :             break;
     598             : 
     599             :         // Notice the fall-through.
     600             :         case EOpVectorTimesScalar:
     601             :         case EOpVectorTimesMatrix:
     602             :         case EOpMatrixTimesVector:
     603             :         case EOpMatrixTimesScalar:
     604             :         case EOpMatrixTimesMatrix:
     605           0 :             writeTriplet(visit, "(", " * ", ")");
     606           0 :             break;
     607             : 
     608             :         case EOpLogicalOr:
     609           0 :             writeTriplet(visit, "(", " || ", ")");
     610           0 :             break;
     611             :         case EOpLogicalXor:
     612           0 :             writeTriplet(visit, "(", " ^^ ", ")");
     613           0 :             break;
     614             :         case EOpLogicalAnd:
     615           0 :             writeTriplet(visit, "(", " && ", ")");
     616           0 :             break;
     617             :         default:
     618           0 :             UNREACHABLE();
     619             :     }
     620             : 
     621           0 :     return visitChildren;
     622             : }
     623             : 
     624           0 : bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
     625             : {
     626           0 :     TString preString;
     627           0 :     TString postString = ")";
     628             : 
     629           0 :     switch (node->getOp())
     630             :     {
     631           0 :       case EOpNegative: preString = "(-"; break;
     632           0 :       case EOpPositive: preString = "(+"; break;
     633           0 :       case EOpVectorLogicalNot: preString = "not("; break;
     634           0 :       case EOpLogicalNot: preString = "(!"; break;
     635           0 :       case EOpBitwiseNot: preString = "(~"; break;
     636             : 
     637           0 :       case EOpPostIncrement: preString = "("; postString = "++)"; break;
     638           0 :       case EOpPostDecrement: preString = "("; postString = "--)"; break;
     639           0 :       case EOpPreIncrement: preString = "(++"; break;
     640           0 :       case EOpPreDecrement: preString = "(--"; break;
     641             : 
     642             :       case EOpRadians:
     643           0 :         preString = "radians(";
     644           0 :         break;
     645             :       case EOpDegrees:
     646           0 :         preString = "degrees(";
     647           0 :         break;
     648             :       case EOpSin:
     649           0 :         preString = "sin(";
     650           0 :         break;
     651             :       case EOpCos:
     652           0 :         preString = "cos(";
     653           0 :         break;
     654             :       case EOpTan:
     655           0 :         preString = "tan(";
     656           0 :         break;
     657             :       case EOpAsin:
     658           0 :         preString = "asin(";
     659           0 :         break;
     660             :       case EOpAcos:
     661           0 :         preString = "acos(";
     662           0 :         break;
     663             :       case EOpAtan:
     664           0 :         preString = "atan(";
     665           0 :         break;
     666             : 
     667             :       case EOpSinh:
     668           0 :         preString = "sinh(";
     669           0 :         break;
     670             :       case EOpCosh:
     671           0 :         preString = "cosh(";
     672           0 :         break;
     673             :       case EOpTanh:
     674           0 :         preString = "tanh(";
     675           0 :         break;
     676             :       case EOpAsinh:
     677           0 :         preString = "asinh(";
     678           0 :         break;
     679             :       case EOpAcosh:
     680           0 :         preString = "acosh(";
     681           0 :         break;
     682             :       case EOpAtanh:
     683           0 :         preString = "atanh(";
     684           0 :         break;
     685             : 
     686             :       case EOpExp:
     687           0 :         preString = "exp(";
     688           0 :         break;
     689             :       case EOpLog:
     690           0 :         preString = "log(";
     691           0 :         break;
     692             :       case EOpExp2:
     693           0 :         preString = "exp2(";
     694           0 :         break;
     695             :       case EOpLog2:
     696           0 :         preString = "log2(";
     697           0 :         break;
     698             :       case EOpSqrt:
     699           0 :         preString = "sqrt(";
     700           0 :         break;
     701             :       case EOpInverseSqrt:
     702           0 :         preString = "inversesqrt(";
     703           0 :         break;
     704             : 
     705             :       case EOpAbs:
     706           0 :         preString = "abs(";
     707           0 :         break;
     708             :       case EOpSign:
     709           0 :         preString = "sign(";
     710           0 :         break;
     711             :       case EOpFloor:
     712           0 :         preString = "floor(";
     713           0 :         break;
     714             :       case EOpTrunc:
     715           0 :         preString = "trunc(";
     716           0 :         break;
     717             :       case EOpRound:
     718           0 :         preString = "round(";
     719           0 :         break;
     720             :       case EOpRoundEven:
     721           0 :         preString = "roundEven(";
     722           0 :         break;
     723             :       case EOpCeil:
     724           0 :         preString = "ceil(";
     725           0 :         break;
     726             :       case EOpFract:
     727           0 :         preString = "fract(";
     728           0 :         break;
     729             :       case EOpIsNan:
     730           0 :         preString = "isnan(";
     731           0 :         break;
     732             :       case EOpIsInf:
     733           0 :         preString = "isinf(";
     734           0 :         break;
     735             : 
     736             :       case EOpFloatBitsToInt:
     737           0 :         preString = "floatBitsToInt(";
     738           0 :         break;
     739             :       case EOpFloatBitsToUint:
     740           0 :         preString = "floatBitsToUint(";
     741           0 :         break;
     742             :       case EOpIntBitsToFloat:
     743           0 :         preString = "intBitsToFloat(";
     744           0 :         break;
     745             :       case EOpUintBitsToFloat:
     746           0 :         preString = "uintBitsToFloat(";
     747           0 :         break;
     748             : 
     749             :       case EOpPackSnorm2x16:
     750           0 :         preString = "packSnorm2x16(";
     751           0 :         break;
     752             :       case EOpPackUnorm2x16:
     753           0 :         preString = "packUnorm2x16(";
     754           0 :         break;
     755             :       case EOpPackHalf2x16:
     756           0 :         preString = "packHalf2x16(";
     757           0 :         break;
     758             :       case EOpUnpackSnorm2x16:
     759           0 :         preString = "unpackSnorm2x16(";
     760           0 :         break;
     761             :       case EOpUnpackUnorm2x16:
     762           0 :         preString = "unpackUnorm2x16(";
     763           0 :         break;
     764             :       case EOpUnpackHalf2x16:
     765           0 :         preString = "unpackHalf2x16(";
     766           0 :         break;
     767             : 
     768             :       case EOpLength:
     769           0 :         preString = "length(";
     770           0 :         break;
     771             :       case EOpNormalize:
     772           0 :         preString = "normalize(";
     773           0 :         break;
     774             : 
     775             :       case EOpDFdx:
     776           0 :         preString = "dFdx(";
     777           0 :         break;
     778             :       case EOpDFdy:
     779           0 :         preString = "dFdy(";
     780           0 :         break;
     781             :       case EOpFwidth:
     782           0 :         preString = "fwidth(";
     783           0 :         break;
     784             : 
     785             :       case EOpTranspose:
     786           0 :         preString = "transpose(";
     787           0 :         break;
     788             :       case EOpDeterminant:
     789           0 :         preString = "determinant(";
     790           0 :         break;
     791             :       case EOpInverse:
     792           0 :         preString = "inverse(";
     793           0 :         break;
     794             : 
     795             :       case EOpAny:
     796           0 :         preString = "any(";
     797           0 :         break;
     798             :       case EOpAll:
     799           0 :         preString = "all(";
     800           0 :         break;
     801             : 
     802             :       default:
     803           0 :         UNREACHABLE();
     804             :     }
     805             : 
     806           0 :     if (visit == PreVisit && node->getUseEmulatedFunction())
     807           0 :         preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
     808           0 :     writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
     809             : 
     810           0 :     return true;
     811             : }
     812             : 
     813           0 : bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node)
     814             : {
     815           0 :     TInfoSinkBase &out = objSink();
     816             :     // Notice two brackets at the beginning and end. The outer ones
     817             :     // encapsulate the whole ternary expression. This preserves the
     818             :     // order of precedence when ternary expressions are used in a
     819             :     // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
     820           0 :     out << "((";
     821           0 :     node->getCondition()->traverse(this);
     822           0 :     out << ") ? (";
     823           0 :     node->getTrueExpression()->traverse(this);
     824           0 :     out << ") : (";
     825           0 :     node->getFalseExpression()->traverse(this);
     826           0 :     out << "))";
     827           0 :     return false;
     828             : }
     829             : 
     830           0 : bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node)
     831             : {
     832           0 :     TInfoSinkBase &out = objSink();
     833             : 
     834           0 :     out << "if (";
     835           0 :     node->getCondition()->traverse(this);
     836           0 :     out << ")\n";
     837             : 
     838           0 :     incrementDepth(node);
     839           0 :     visitCodeBlock(node->getTrueBlock());
     840             : 
     841           0 :     if (node->getFalseBlock())
     842             :     {
     843           0 :         out << "else\n";
     844           0 :         visitCodeBlock(node->getFalseBlock());
     845             :     }
     846           0 :     decrementDepth();
     847           0 :     return false;
     848             : }
     849             : 
     850           0 : bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
     851             : {
     852           0 :     if (node->getStatementList())
     853             :     {
     854           0 :         writeTriplet(visit, "switch (", ") ", nullptr);
     855             :         // The curly braces get written when visiting the statementList aggregate
     856             :     }
     857             :     else
     858             :     {
     859             :         // No statementList, so it won't output curly braces
     860           0 :         writeTriplet(visit, "switch (", ") {", "}\n");
     861             :     }
     862           0 :     return true;
     863             : }
     864             : 
     865           0 : bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
     866             : {
     867           0 :     if (node->hasCondition())
     868             :     {
     869           0 :         writeTriplet(visit, "case (", nullptr, "):\n");
     870           0 :         return true;
     871             :     }
     872             :     else
     873             :     {
     874           0 :         TInfoSinkBase &out = objSink();
     875           0 :         out << "default:\n";
     876           0 :         return false;
     877             :     }
     878             : }
     879             : 
     880           0 : bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
     881             : {
     882           0 :     TInfoSinkBase &out = objSink();
     883             :     // Scope the blocks except when at the global scope.
     884           0 :     if (mDepth > 0)
     885             :     {
     886           0 :         out << "{\n";
     887             :     }
     888             : 
     889           0 :     incrementDepth(node);
     890           0 :     for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
     891           0 :          iter != node->getSequence()->end(); ++iter)
     892             :     {
     893           0 :         TIntermNode *curNode = *iter;
     894           0 :         ASSERT(curNode != nullptr);
     895           0 :         curNode->traverse(this);
     896             : 
     897           0 :         if (isSingleStatement(curNode))
     898           0 :             out << ";\n";
     899             :     }
     900           0 :     decrementDepth();
     901             : 
     902             :     // Scope the blocks except when at the global scope.
     903           0 :     if (mDepth > 0)
     904             :     {
     905           0 :         out << "}\n";
     906             :     }
     907           0 :     return false;
     908             : }
     909             : 
     910           0 : bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
     911             : {
     912           0 :     TInfoSinkBase &out = objSink();
     913             : 
     914           0 :     ASSERT(visit == PreVisit);
     915             :     {
     916           0 :         const TType &type = node->getType();
     917           0 :         writeVariableType(type);
     918           0 :         if (type.isArray())
     919           0 :             out << arrayBrackets(type);
     920             :     }
     921             : 
     922           0 :     out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
     923             : 
     924           0 :     incrementDepth(node);
     925             : 
     926             :     // Traverse function parameters.
     927           0 :     TIntermAggregate *params = node->getFunctionParameters()->getAsAggregate();
     928           0 :     ASSERT(params->getOp() == EOpParameters);
     929           0 :     params->traverse(this);
     930             : 
     931             :     // Traverse function body.
     932           0 :     visitCodeBlock(node->getBody());
     933           0 :     decrementDepth();
     934             : 
     935             :     // Fully processed; no need to visit children.
     936           0 :     return false;
     937             : }
     938             : 
     939           0 : bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
     940             : {
     941           0 :     bool visitChildren = true;
     942           0 :     TInfoSinkBase &out = objSink();
     943           0 :     bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
     944           0 :     switch (node->getOp())
     945             :     {
     946             :       case EOpPrototype:
     947             :         // Function declaration.
     948           0 :         ASSERT(visit == PreVisit);
     949             :         {
     950           0 :             const TType &type = node->getType();
     951           0 :             writeVariableType(type);
     952           0 :             if (type.isArray())
     953           0 :                 out << arrayBrackets(type);
     954             :         }
     955             : 
     956           0 :         out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
     957             : 
     958           0 :         out << "(";
     959           0 :         writeFunctionParameters(*(node->getSequence()));
     960           0 :         out << ")";
     961             : 
     962           0 :         visitChildren = false;
     963           0 :         break;
     964             :       case EOpFunctionCall:
     965             :         // Function call.
     966           0 :         if (visit == PreVisit)
     967           0 :             out << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
     968           0 :         else if (visit == InVisit)
     969           0 :             out << ", ";
     970             :         else
     971           0 :             out << ")";
     972           0 :         break;
     973             :       case EOpParameters:
     974             :         // Function parameters.
     975           0 :         ASSERT(visit == PreVisit);
     976           0 :         out << "(";
     977           0 :         writeFunctionParameters(*(node->getSequence()));
     978           0 :         out << ")";
     979           0 :         visitChildren = false;
     980           0 :         break;
     981             :       case EOpInvariantDeclaration:
     982             :         // Invariant declaration.
     983           0 :         ASSERT(visit == PreVisit);
     984             :         {
     985           0 :             const TIntermSequence *sequence = node->getSequence();
     986           0 :             ASSERT(sequence && sequence->size() == 1);
     987           0 :             const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
     988           0 :             ASSERT(symbol);
     989           0 :             out << "invariant " << hashVariableName(symbol->getName());
     990             :         }
     991           0 :         visitChildren = false;
     992           0 :         break;
     993             :       case EOpConstructFloat:
     994             :       case EOpConstructVec2:
     995             :       case EOpConstructVec3:
     996             :       case EOpConstructVec4:
     997             :       case EOpConstructBool:
     998             :       case EOpConstructBVec2:
     999             :       case EOpConstructBVec3:
    1000             :       case EOpConstructBVec4:
    1001             :       case EOpConstructInt:
    1002             :       case EOpConstructIVec2:
    1003             :       case EOpConstructIVec3:
    1004             :       case EOpConstructIVec4:
    1005             :       case EOpConstructUInt:
    1006             :       case EOpConstructUVec2:
    1007             :       case EOpConstructUVec3:
    1008             :       case EOpConstructUVec4:
    1009             :       case EOpConstructMat2:
    1010             :       case EOpConstructMat2x3:
    1011             :       case EOpConstructMat2x4:
    1012             :       case EOpConstructMat3x2:
    1013             :       case EOpConstructMat3:
    1014             :       case EOpConstructMat3x4:
    1015             :       case EOpConstructMat4x2:
    1016             :       case EOpConstructMat4x3:
    1017             :       case EOpConstructMat4:
    1018             :       case EOpConstructStruct:
    1019           0 :           writeConstructorTriplet(visit, node->getType());
    1020           0 :           break;
    1021             : 
    1022             :       case EOpOuterProduct:
    1023           0 :         writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
    1024           0 :         break;
    1025             : 
    1026             :       case EOpLessThan:
    1027           0 :         writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
    1028           0 :         break;
    1029             :       case EOpGreaterThan:
    1030           0 :         writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction);
    1031           0 :         break;
    1032             :       case EOpLessThanEqual:
    1033           0 :         writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction);
    1034           0 :         break;
    1035             :       case EOpGreaterThanEqual:
    1036           0 :         writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction);
    1037           0 :         break;
    1038             :       case EOpVectorEqual:
    1039           0 :         writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction);
    1040           0 :         break;
    1041             :       case EOpVectorNotEqual:
    1042           0 :         writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
    1043           0 :         break;
    1044             : 
    1045             :       case EOpMod:
    1046           0 :         writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
    1047           0 :         break;
    1048             :       case EOpModf:
    1049           0 :         writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
    1050           0 :         break;
    1051             :       case EOpPow:
    1052           0 :         writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
    1053           0 :         break;
    1054             :       case EOpAtan:
    1055           0 :         writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction);
    1056           0 :         break;
    1057             :       case EOpMin:
    1058           0 :         writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction);
    1059           0 :         break;
    1060             :       case EOpMax:
    1061           0 :         writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction);
    1062           0 :         break;
    1063             :       case EOpClamp:
    1064           0 :         writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction);
    1065           0 :         break;
    1066             :       case EOpMix:
    1067           0 :         writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction);
    1068           0 :         break;
    1069             :       case EOpStep:
    1070           0 :         writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction);
    1071           0 :         break;
    1072             :       case EOpSmoothStep:
    1073           0 :         writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction);
    1074           0 :         break;
    1075             :       case EOpDistance:
    1076           0 :         writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction);
    1077           0 :         break;
    1078             :       case EOpDot:
    1079           0 :         writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction);
    1080           0 :         break;
    1081             :       case EOpCross:
    1082           0 :         writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction);
    1083           0 :         break;
    1084             :       case EOpFaceForward:
    1085           0 :         writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction);
    1086           0 :         break;
    1087             :       case EOpReflect:
    1088           0 :         writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction);
    1089           0 :         break;
    1090             :       case EOpRefract:
    1091           0 :         writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction);
    1092           0 :         break;
    1093             :       case EOpMul:
    1094           0 :         writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
    1095           0 :         break;
    1096             : 
    1097             :       default:
    1098           0 :         UNREACHABLE();
    1099             :     }
    1100           0 :     return visitChildren;
    1101             : }
    1102             : 
    1103           0 : bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
    1104             : {
    1105           0 :     TInfoSinkBase &out = objSink();
    1106             : 
    1107             :     // Variable declaration.
    1108           0 :     if (visit == PreVisit)
    1109             :     {
    1110           0 :         const TIntermSequence &sequence = *(node->getSequence());
    1111           0 :         const TIntermTyped *variable    = sequence.front()->getAsTyped();
    1112           0 :         writeLayoutQualifier(variable->getType());
    1113           0 :         writeVariableType(variable->getType());
    1114           0 :         out << " ";
    1115           0 :         mDeclaringVariables = true;
    1116             :     }
    1117           0 :     else if (visit == InVisit)
    1118             :     {
    1119           0 :         out << ", ";
    1120           0 :         mDeclaringVariables = true;
    1121             :     }
    1122             :     else
    1123             :     {
    1124           0 :         mDeclaringVariables = false;
    1125             :     }
    1126           0 :     return true;
    1127             : }
    1128             : 
    1129           0 : bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
    1130             : {
    1131           0 :     TInfoSinkBase &out = objSink();
    1132             : 
    1133           0 :     incrementDepth(node);
    1134             : 
    1135           0 :     TLoopType loopType = node->getType();
    1136             : 
    1137           0 :     if (loopType == ELoopFor)  // for loop
    1138             :     {
    1139           0 :         out << "for (";
    1140           0 :         if (node->getInit())
    1141           0 :             node->getInit()->traverse(this);
    1142           0 :         out << "; ";
    1143             : 
    1144           0 :         if (node->getCondition())
    1145           0 :             node->getCondition()->traverse(this);
    1146           0 :         out << "; ";
    1147             : 
    1148           0 :         if (node->getExpression())
    1149           0 :             node->getExpression()->traverse(this);
    1150           0 :         out << ")\n";
    1151             : 
    1152           0 :         visitCodeBlock(node->getBody());
    1153             :     }
    1154           0 :     else if (loopType == ELoopWhile)  // while loop
    1155             :     {
    1156           0 :         out << "while (";
    1157           0 :         ASSERT(node->getCondition() != NULL);
    1158           0 :         node->getCondition()->traverse(this);
    1159           0 :         out << ")\n";
    1160             : 
    1161           0 :         visitCodeBlock(node->getBody());
    1162             :     }
    1163             :     else  // do-while loop
    1164             :     {
    1165           0 :         ASSERT(loopType == ELoopDoWhile);
    1166           0 :         out << "do\n";
    1167             : 
    1168           0 :         visitCodeBlock(node->getBody());
    1169             : 
    1170           0 :         out << "while (";
    1171           0 :         ASSERT(node->getCondition() != NULL);
    1172           0 :         node->getCondition()->traverse(this);
    1173           0 :         out << ");\n";
    1174             :     }
    1175             : 
    1176           0 :     decrementDepth();
    1177             : 
    1178             :     // No need to visit children. They have been already processed in
    1179             :     // this function.
    1180           0 :     return false;
    1181             : }
    1182             : 
    1183           0 : bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
    1184             : {
    1185           0 :     switch (node->getFlowOp())
    1186             :     {
    1187             :       case EOpKill:
    1188           0 :         writeTriplet(visit, "discard", NULL, NULL);
    1189           0 :         break;
    1190             :       case EOpBreak:
    1191           0 :         writeTriplet(visit, "break", NULL, NULL);
    1192           0 :         break;
    1193             :       case EOpContinue:
    1194           0 :         writeTriplet(visit, "continue", NULL, NULL);
    1195           0 :         break;
    1196             :       case EOpReturn:
    1197           0 :         writeTriplet(visit, "return ", NULL, NULL);
    1198           0 :         break;
    1199             :       default:
    1200           0 :         UNREACHABLE();
    1201             :     }
    1202             : 
    1203           0 :     return true;
    1204             : }
    1205             : 
    1206           0 : void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
    1207             : {
    1208           0 :     TInfoSinkBase &out = objSink();
    1209           0 :     if (node != NULL)
    1210             :     {
    1211           0 :         node->traverse(this);
    1212             :         // Single statements not part of a sequence need to be terminated
    1213             :         // with semi-colon.
    1214           0 :         if (isSingleStatement(node))
    1215           0 :             out << ";\n";
    1216             :     }
    1217             :     else
    1218             :     {
    1219           0 :         out << "{\n}\n";  // Empty code block.
    1220             :     }
    1221           0 : }
    1222             : 
    1223           0 : TString TOutputGLSLBase::getTypeName(const TType &type)
    1224             : {
    1225           0 :     if (type.getBasicType() == EbtStruct)
    1226           0 :         return hashName(TName(type.getStruct()->name()));
    1227             :     else
    1228           0 :         return type.getBuiltInTypeNameString();
    1229             : }
    1230             : 
    1231           0 : TString TOutputGLSLBase::hashName(const TName &name)
    1232             : {
    1233           0 :     if (name.getString().empty())
    1234             :     {
    1235           0 :         ASSERT(!name.isInternal());
    1236           0 :         return name.getString();
    1237             :     }
    1238           0 :     if (name.isInternal())
    1239             :     {
    1240             :         // TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is
    1241             :         // done in the HLSL output, but that requires fairly complex changes elsewhere in the code
    1242             :         // as well.
    1243             :         // We need to use a prefix that is reserved in WebGL in order to guarantee that the internal
    1244             :         // names don't conflict with user-defined names from WebGL.
    1245           0 :         return "webgl_angle_" + name.getString();
    1246             :     }
    1247           0 :     if (mHashFunction == nullptr)
    1248             :     {
    1249           0 :         return name.getString();
    1250             :     }
    1251           0 :     NameMap::const_iterator it = mNameMap.find(name.getString().c_str());
    1252           0 :     if (it != mNameMap.end())
    1253           0 :         return it->second.c_str();
    1254           0 :     TString hashedName                 = TIntermTraverser::hash(name.getString(), mHashFunction);
    1255           0 :     mNameMap[name.getString().c_str()] = hashedName.c_str();
    1256           0 :     return hashedName;
    1257             : }
    1258             : 
    1259           0 : TString TOutputGLSLBase::hashVariableName(const TName &name)
    1260             : {
    1261           0 :     if (mSymbolTable.findBuiltIn(name.getString(), mShaderVersion) != NULL)
    1262           0 :         return name.getString();
    1263           0 :     return hashName(name);
    1264             : }
    1265             : 
    1266           0 : TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName)
    1267             : {
    1268           0 :     TString mangledStr = mangledName.getString();
    1269           0 :     TString name = TFunction::unmangleName(mangledStr);
    1270           0 :     if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main")
    1271           0 :         return translateTextureFunction(name);
    1272           0 :     if (mangledName.isInternal())
    1273             :     {
    1274             :         // Internal function names are outputted as-is - they may refer to functions manually added
    1275             :         // to the output shader source that are not included in the AST at all.
    1276           0 :         return name;
    1277             :     }
    1278             :     else
    1279             :     {
    1280           0 :         TName nameObj(name);
    1281           0 :         return hashName(nameObj);
    1282             :     }
    1283             : }
    1284             : 
    1285           0 : bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
    1286             : {
    1287           0 :     ASSERT(structure);
    1288           0 :     if (structure->name().empty())
    1289             :     {
    1290           0 :         return false;
    1291             :     }
    1292             : 
    1293           0 :     return (mDeclaredStructs.count(structure->uniqueId()) > 0);
    1294             : }
    1295             : 
    1296           0 : void TOutputGLSLBase::declareStruct(const TStructure *structure)
    1297             : {
    1298           0 :     TInfoSinkBase &out = objSink();
    1299             : 
    1300           0 :     out << "struct " << hashName(TName(structure->name())) << "{\n";
    1301           0 :     const TFieldList &fields = structure->fields();
    1302           0 :     for (size_t i = 0; i < fields.size(); ++i)
    1303             :     {
    1304           0 :         const TField *field = fields[i];
    1305           0 :         if (writeVariablePrecision(field->type()->getPrecision()))
    1306           0 :             out << " ";
    1307           0 :         out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
    1308           0 :         if (field->type()->isArray())
    1309           0 :             out << arrayBrackets(*field->type());
    1310           0 :         out << ";\n";
    1311             :     }
    1312           0 :     out << "}";
    1313           0 : }
    1314             : 
    1315           0 : void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
    1316             : {
    1317           0 :     TInfoSinkBase &out = objSink();
    1318             : 
    1319           0 :     out << "layout(";
    1320             : 
    1321           0 :     switch (interfaceBlock->blockStorage())
    1322             :     {
    1323             :         case EbsUnspecified:
    1324             :         case EbsShared:
    1325             :             // Default block storage is shared.
    1326           0 :             out << "shared";
    1327           0 :             break;
    1328             : 
    1329             :         case EbsPacked:
    1330           0 :             out << "packed";
    1331           0 :             break;
    1332             : 
    1333             :         case EbsStd140:
    1334           0 :             out << "std140";
    1335           0 :             break;
    1336             : 
    1337             :         default:
    1338           0 :             UNREACHABLE();
    1339             :             break;
    1340             :     }
    1341             : 
    1342           0 :     out << ", ";
    1343             : 
    1344           0 :     switch (interfaceBlock->matrixPacking())
    1345             :     {
    1346             :         case EmpUnspecified:
    1347             :         case EmpColumnMajor:
    1348             :             // Default matrix packing is column major.
    1349           0 :             out << "column_major";
    1350           0 :             break;
    1351             : 
    1352             :         case EmpRowMajor:
    1353           0 :             out << "row_major";
    1354           0 :             break;
    1355             : 
    1356             :         default:
    1357           0 :             UNREACHABLE();
    1358             :             break;
    1359             :     }
    1360             : 
    1361           0 :     out << ") ";
    1362           0 : }
    1363             : 
    1364           0 : void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock)
    1365             : {
    1366           0 :     TInfoSinkBase &out = objSink();
    1367             : 
    1368           0 :     out << hashName(TName(interfaceBlock->name())) << "{\n";
    1369           0 :     const TFieldList &fields = interfaceBlock->fields();
    1370           0 :     for (size_t i = 0; i < fields.size(); ++i)
    1371             :     {
    1372           0 :         const TField *field = fields[i];
    1373           0 :         if (writeVariablePrecision(field->type()->getPrecision()))
    1374           0 :             out << " ";
    1375           0 :         out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
    1376           0 :         if (field->type()->isArray())
    1377           0 :             out << arrayBrackets(*field->type());
    1378           0 :         out << ";\n";
    1379             :     }
    1380           0 :     out << "}";
    1381           0 : }
    1382             : 
    1383             : }  // namespace sh

Generated by: LCOV version 1.13