diff options
Diffstat (limited to 'gfx/angle/src/compiler/translator/OutputGLSLBase.cpp')
-rwxr-xr-x | gfx/angle/src/compiler/translator/OutputGLSLBase.cpp | 891 |
1 files changed, 390 insertions, 501 deletions
diff --git a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp index 2c32b2ea5..296eef7d1 100755 --- a/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/gfx/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -10,9 +10,6 @@ #include <cfloat> -namespace sh -{ - namespace { TString arrayBrackets(const TType &type) @@ -25,17 +22,16 @@ TString arrayBrackets(const TType &type) bool isSingleStatement(TIntermNode *node) { - if (node->getAsFunctionDefinition()) - { - return false; - } - else if (node->getAsBlock()) + if (const TIntermAggregate *aggregate = node->getAsAggregate()) { - return false; + return (aggregate->getOp() != EOpFunction) && + (aggregate->getOp() != EOpSequence); } - else if (node->getAsIfElseNode()) + else if (const TIntermSelection *selection = node->getAsSelectionNode()) { - return false; + // Ternary operators are usually part of an assignment operator. + // This handles those rare cases in which they are all by themselves. + return selection->usesTernaryOperator(); } else if (node->getAsLoopNode()) { @@ -52,32 +48,6 @@ bool isSingleStatement(TIntermNode *node) return true; } -// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever -// variables with specified layout qualifiers are copied. Additional checks are needed against the -// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted. -// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove -// NeedsToWriteLayoutQualifier. -bool NeedsToWriteLayoutQualifier(const TType &type) -{ - if (type.getBasicType() == EbtInterfaceBlock) - { - return false; - } - - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - - if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) && - layoutQualifier.location >= 0) - { - return true; - } - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - return true; - } - return false; -} - } // namespace TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, @@ -85,10 +55,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable, - sh::GLenum shaderType, int shaderVersion, - ShShaderOutput output, - ShCompileOptions compileOptions) + ShShaderOutput output) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), @@ -96,20 +64,9 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, mHashFunction(hashFunction), mNameMap(nameMap), mSymbolTable(symbolTable), - mShaderType(shaderType), mShaderVersion(shaderVersion), - mOutput(output), - mCompileOptions(compileOptions) -{ -} - -void TOutputGLSLBase::writeInvariantQualifier(const TType &type) + mOutput(output) { - if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions)) - { - TInfoSinkBase &out = objSink(); - out << "invariant "; - } } void TOutputGLSLBase::writeTriplet( @@ -134,121 +91,55 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet( void TOutputGLSLBase::writeLayoutQualifier(const TType &type) { - if (!NeedsToWriteLayoutQualifier(type)) - { - return; - } - - TInfoSinkBase &out = objSink(); - const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); - out << "layout("; - if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) { + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); if (layoutQualifier.location >= 0) { - out << "location = " << layoutQualifier.location; + TInfoSinkBase &out = objSink(); + out << "layout(location = " << layoutQualifier.location << ") "; } } - - if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified) - { - ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform); - out << getImageInternalFormatString(layoutQualifier.imageInternalFormat); - } - - out << ") "; -} - -const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) -{ - if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 && - (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0) - { - switch (qualifier) - { - // The return string is consistent with sh::getQualifierString() from - // BaseTypes.h minus the "centroid" keyword. - case EvqCentroid: - return ""; - case EvqCentroidIn: - return "smooth in"; - case EvqCentroidOut: - return "smooth out"; - default: - break; - } - } - if (sh::IsGLSL130OrNewer(mOutput)) - { - switch (qualifier) - { - case EvqAttribute: - return "in"; - case EvqVaryingIn: - return "in"; - case EvqVaryingOut: - return "out"; - default: - break; - } - } - return sh::getQualifierString(qualifier); } void TOutputGLSLBase::writeVariableType(const TType &type) { - TQualifier qualifier = type.getQualifier(); TInfoSinkBase &out = objSink(); if (type.isInvariant()) { - writeInvariantQualifier(type); + out << "invariant "; } if (type.getBasicType() == EbtInterfaceBlock) { TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); declareInterfaceBlockLayout(interfaceBlock); } + TQualifier qualifier = type.getQualifier(); if (qualifier != EvqTemporary && qualifier != EvqGlobal) { - const char *qualifierString = mapQualifierToString(qualifier); - if (qualifierString && qualifierString[0] != '\0') + if (IsGLSL130OrNewer(mOutput)) { - out << qualifierString << " "; + switch (qualifier) + { + case EvqAttribute: + out << "in "; + break; + case EvqVaryingIn: + out << "in "; + break; + case EvqVaryingOut: + out << "out "; + break; + default: + out << type.getQualifierString() << " "; + break; + } + } + else + { + out << type.getQualifierString() << " "; } } - - const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); - if (memoryQualifier.readonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "readonly "; - } - - if (memoryQualifier.writeonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "writeonly "; - } - - if (memoryQualifier.coherent) - { - ASSERT(IsImage(type.getBasicType())); - out << "coherent "; - } - - if (memoryQualifier.restrictQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "restrict "; - } - - if (memoryQualifier.volatileQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "volatile "; - } - // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { @@ -286,8 +177,9 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) const TType &type = arg->getType(); writeVariableType(type); - if (!arg->getName().getString().empty()) - out << " " << hashName(arg->getName()); + const TString &name = arg->getSymbol(); + if (!name.empty()) + out << " " << hashName(name); if (type.isArray()) out << arrayBrackets(type); @@ -305,7 +197,7 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion( if (type.getBasicType() == EbtStruct) { const TStructure *structure = type.getStruct(); - out << hashName(TName(structure->name())) << "("; + out << hashName(structure->name()) << "("; const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) @@ -379,7 +271,7 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node)) out << mLoopUnrollStack.getLoopIndexValue(node); else - out << hashVariableName(node->getName()); + out << hashVariableName(node->getSymbol()); if (mDeclaringVariables && node->getType().isArray()) out << arrayBrackets(node->getType()); @@ -390,222 +282,241 @@ void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) writeConstantUnion(node->getType(), node->getUnionArrayPointer()); } -bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node) -{ - TInfoSinkBase &out = objSink(); - if (visit == PostVisit) - { - out << "."; - node->writeOffsetsAsXYZW(&out); - } - return true; -} - bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) { bool visitChildren = true; TInfoSinkBase &out = objSink(); switch (node->getOp()) { - case EOpComma: - writeTriplet(visit, "(", ", ", ")"); - break; - case EOpInitialize: + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: + writeTriplet(visit, "(", " = ", ")"); + break; + case EOpAddAssign: + writeTriplet(visit, "(", " += ", ")"); + break; + case EOpSubAssign: + writeTriplet(visit, "(", " -= ", ")"); + break; + case EOpDivAssign: + writeTriplet(visit, "(", " /= ", ")"); + break; + case EOpIModAssign: + writeTriplet(visit, "(", " %= ", ")"); + break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + case EOpBitShiftLeftAssign: + writeTriplet(visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + writeTriplet(visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + writeTriplet(visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + writeTriplet(visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + writeTriplet(visit, "(", " |= ", ")"); + break; + + case EOpIndexDirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexIndirect: + if (node->getAddIndexClamp()) + { if (visit == InVisit) { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariables = false; + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "[int(clamp(float("; + else + out << "[webgl_int_clamp("; } - break; - case EOpAssign: - writeTriplet(visit, "(", " = ", ")"); - break; - case EOpAddAssign: - writeTriplet(visit, "(", " += ", ")"); - break; - case EOpSubAssign: - writeTriplet(visit, "(", " -= ", ")"); - break; - case EOpDivAssign: - writeTriplet(visit, "(", " /= ", ")"); - break; - case EOpIModAssign: - writeTriplet(visit, "(", " %= ", ")"); - break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - case EOpBitShiftLeftAssign: - writeTriplet(visit, "(", " <<= ", ")"); - break; - case EOpBitShiftRightAssign: - writeTriplet(visit, "(", " >>= ", ")"); - break; - case EOpBitwiseAndAssign: - writeTriplet(visit, "(", " &= ", ")"); - break; - case EOpBitwiseXorAssign: - writeTriplet(visit, "(", " ^= ", ")"); - break; - case EOpBitwiseOrAssign: - writeTriplet(visit, "(", " |= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, NULL, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) + else if (visit == PostVisit) { - if (visit == InVisit) + int maxSize; + TIntermTyped *left = node->getLeft(); + TType leftType = left->getType(); + + if (left->isArray()) { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "[int(clamp(float("; - else - out << "[webgl_int_clamp("; + // The shader will fail validation if the array length is not > 0. + maxSize = static_cast<int>(leftType.getArraySize()) - 1; } - else if (visit == PostVisit) + else { - int maxSize; - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (left->isArray()) - { - // The shader will fail validation if the array length is not > 0. - maxSize = static_cast<int>(leftType.getArraySize()) - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) - out << "), 0.0, float(" << maxSize << ")))]"; - else - out << ", 0, " << maxSize << ")]"; + maxSize = leftType.getNominalSize() - 1; } + + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "), 0.0, float(" << maxSize << ")))]"; + else + out << ", 0, " << maxSize << ")]"; } - else - { - writeTriplet(visit, NULL, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure *structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; - } - break; - case EOpIndexDirectInterfaceBlock: - if (visit == InVisit) + } + else + { + writeTriplet(visit, NULL, "[", "]"); + } + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpIndexDirectInterfaceBlock: + if (visit == InVisit) + { + out << "."; + const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = interfaceBlock->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion)); + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate *rightChild = node->getRight()->getAsAggregate(); + TIntermSequence *sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit) { - out << "."; - const TInterfaceBlock *interfaceBlock = - node->getLeft()->getType().getInterfaceBlock(); - const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); - const TField *field = interfaceBlock->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion)); - fieldName = hashName(TName(fieldName)); - - out << fieldName; - visitChildren = false; + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const TConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) + { + case 0: + out << "x"; + break; + case 1: + out << "y"; + break; + case 2: + out << "z"; + break; + case 3: + out << "w"; + break; + default: + UNREACHABLE(); + } } - break; + visitChildren = false; + } + break; - case EOpAdd: - writeTriplet(visit, "(", " + ", ")"); - break; - case EOpSub: - writeTriplet(visit, "(", " - ", ")"); - break; - case EOpMul: - writeTriplet(visit, "(", " * ", ")"); - break; - case EOpDiv: - writeTriplet(visit, "(", " / ", ")"); - break; - case EOpIMod: - writeTriplet(visit, "(", " % ", ")"); - break; - case EOpBitShiftLeft: - writeTriplet(visit, "(", " << ", ")"); - break; - case EOpBitShiftRight: - writeTriplet(visit, "(", " >> ", ")"); - break; - case EOpBitwiseAnd: - writeTriplet(visit, "(", " & ", ")"); - break; - case EOpBitwiseXor: - writeTriplet(visit, "(", " ^ ", ")"); - break; - case EOpBitwiseOr: - writeTriplet(visit, "(", " | ", ")"); - break; + case EOpAdd: + writeTriplet(visit, "(", " + ", ")"); + break; + case EOpSub: + writeTriplet(visit, "(", " - ", ")"); + break; + case EOpMul: + writeTriplet(visit, "(", " * ", ")"); + break; + case EOpDiv: + writeTriplet(visit, "(", " / ", ")"); + break; + case EOpIMod: + writeTriplet(visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + writeTriplet(visit, "(", " << ", ")"); + break; + case EOpBitShiftRight: + writeTriplet(visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + writeTriplet(visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + writeTriplet(visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + writeTriplet(visit, "(", " | ", ")"); + break; - case EOpEqual: - writeTriplet(visit, "(", " == ", ")"); - break; - case EOpNotEqual: - writeTriplet(visit, "(", " != ", ")"); - break; - case EOpLessThan: - writeTriplet(visit, "(", " < ", ")"); - break; - case EOpGreaterThan: - writeTriplet(visit, "(", " > ", ")"); - break; - case EOpLessThanEqual: - writeTriplet(visit, "(", " <= ", ")"); - break; - case EOpGreaterThanEqual: - writeTriplet(visit, "(", " >= ", ")"); - break; + case EOpEqual: + writeTriplet(visit, "(", " == ", ")"); + break; + case EOpNotEqual: + writeTriplet(visit, "(", " != ", ")"); + break; + case EOpLessThan: + writeTriplet(visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + writeTriplet(visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + writeTriplet(visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + writeTriplet(visit, "(", " >= ", ")"); + break; - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; - case EOpLogicalOr: - writeTriplet(visit, "(", " || ", ")"); - break; - case EOpLogicalXor: - writeTriplet(visit, "(", " ^^ ", ")"); - break; - case EOpLogicalAnd: - writeTriplet(visit, "(", " && ", ")"); - break; - default: - UNREACHABLE(); + case EOpLogicalOr: + writeTriplet(visit, "(", " || ", ")"); + break; + case EOpLogicalXor: + writeTriplet(visit, "(", " ^^ ", ")"); + break; + case EOpLogicalAnd: + writeTriplet(visit, "(", " && ", ")"); + break; + default: + UNREACHABLE(); } return visitChildren; @@ -800,40 +711,40 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) return true; } -bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node) +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) { TInfoSinkBase &out = objSink(); - // Notice two brackets at the beginning and end. The outer ones - // encapsulate the whole ternary expression. This preserves the - // order of precedence when ternary expressions are used in a - // compound expression, i.e., c = 2 * (a < b ? 1 : 2). - out << "(("; - node->getCondition()->traverse(this); - out << ") ? ("; - node->getTrueExpression()->traverse(this); - out << ") : ("; - node->getFalseExpression()->traverse(this); - out << "))"; - return false; -} -bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node) -{ - TInfoSinkBase &out = objSink(); - - out << "if ("; - node->getCondition()->traverse(this); - out << ")\n"; + if (node->usesTernaryOperator()) + { + // Notice two brackets at the beginning and end. The outer ones + // encapsulate the whole ternary expression. This preserves the + // order of precedence when ternary expressions are used in a + // compound expression, i.e., c = 2 * (a < b ? 1 : 2). + out << "(("; + node->getCondition()->traverse(this); + out << ") ? ("; + node->getTrueBlock()->traverse(this); + out << ") : ("; + node->getFalseBlock()->traverse(this); + out << "))"; + } + else + { + out << "if ("; + node->getCondition()->traverse(this); + out << ")\n"; - incrementDepth(node); - visitCodeBlock(node->getTrueBlock()); + incrementDepth(node); + visitCodeBlock(node->getTrueBlock()); - if (node->getFalseBlock()) - { - out << "else\n"; - visitCodeBlock(node->getFalseBlock()); + if (node->getFalseBlock()) + { + out << "else\n"; + visitCodeBlock(node->getFalseBlock()); + } + decrementDepth(); } - decrementDepth(); return false; } @@ -867,65 +778,6 @@ bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) } } -bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node) -{ - TInfoSinkBase &out = objSink(); - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "{\n"; - } - - incrementDepth(node); - for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); - iter != node->getSequence()->end(); ++iter) - { - TIntermNode *curNode = *iter; - ASSERT(curNode != nullptr); - curNode->traverse(this); - - if (isSingleStatement(curNode)) - out << ";\n"; - } - decrementDepth(); - - // Scope the blocks except when at the global scope. - if (mDepth > 0) - { - out << "}\n"; - } - return false; -} - -bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) -{ - TInfoSinkBase &out = objSink(); - - ASSERT(visit == PreVisit); - { - const TType &type = node->getType(); - writeVariableType(type); - if (type.isArray()) - out << arrayBrackets(type); - } - - out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); - - incrementDepth(node); - - // Traverse function parameters. - TIntermAggregate *params = node->getFunctionParameters()->getAsAggregate(); - ASSERT(params->getOp() == EOpParameters); - params->traverse(this); - - // Traverse function body. - visitCodeBlock(node->getBody()); - decrementDepth(); - - // Fully processed; no need to visit children. - return false; -} - bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; @@ -933,6 +785,33 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); switch (node->getOp()) { + case EOpSequence: + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "{\n"; + } + + incrementDepth(node); + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *curNode = *iter; + ASSERT(curNode != NULL); + curNode->traverse(this); + + if (isSingleStatement(curNode)) + out << ";\n"; + } + decrementDepth(); + + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "}\n"; + } + visitChildren = false; + break; case EOpPrototype: // Function declaration. ASSERT(visit == PreVisit); @@ -943,7 +822,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) out << arrayBrackets(type); } - out << " " << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()); + out << " " << hashFunctionNameIfNeeded(node->getNameObj()); out << "("; writeFunctionParameters(*(node->getSequence())); @@ -951,10 +830,46 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) visitChildren = false; break; + case EOpFunction: { + // Function definition. + ASSERT(visit == PreVisit); + { + const TType &type = node->getType(); + writeVariableType(type); + if (type.isArray()) + out << arrayBrackets(type); + } + + out << " " << hashFunctionNameIfNeeded(node->getNameObj()); + + incrementDepth(node); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate *body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } case EOpFunctionCall: // Function call. if (visit == PreVisit) - out << hashFunctionNameIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "("; + out << hashFunctionNameIfNeeded(node->getNameObj()) << "("; else if (visit == InVisit) out << ", "; else @@ -968,6 +883,27 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) out << ")"; visitChildren = false; break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + const TIntermTyped *variable = sequence.front()->getAsTyped(); + writeLayoutQualifier(variable->getType()); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; case EOpInvariantDeclaration: // Invariant declaration. ASSERT(visit == PreVisit); @@ -976,7 +912,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ASSERT(sequence && sequence->size() == 1); const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); ASSERT(symbol); - out << "invariant " << hashVariableName(symbol->getName()); + out << "invariant " << hashVariableName(symbol->getSymbol()); } visitChildren = false; break; @@ -1031,6 +967,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); break; + case EOpComma: + writeTriplet(visit, "(", ", ", ")"); + break; case EOpMod: writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); @@ -1090,32 +1029,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) return visitChildren; } -bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) -{ - TInfoSinkBase &out = objSink(); - - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence &sequence = *(node->getSequence()); - const TIntermTyped *variable = sequence.front()->getAsTyped(); - writeLayoutQualifier(variable->getType()); - writeVariableType(variable->getType()); - out << " "; - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - out << ", "; - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - return true; -} - bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) { TInfoSinkBase &out = objSink(); @@ -1149,10 +1062,11 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) else { // Need to put a one-iteration loop here to handle break. - TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence(); + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); TIntermSymbol *indexSymbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - TString name = hashVariableName(indexSymbol->getName()); + TString name = hashVariableName(indexSymbol->getSymbol()); out << "for (int " << name << " = 0; " << name << " < 1; " << "++" << name << ")\n"; @@ -1220,7 +1134,7 @@ bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) return true; } -void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) +void TOutputGLSLBase::visitCodeBlock(TIntermNode *node) { TInfoSinkBase &out = objSink(); if (node != NULL) @@ -1240,43 +1154,27 @@ void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node) TString TOutputGLSLBase::getTypeName(const TType &type) { if (type.getBasicType() == EbtStruct) - return hashName(TName(type.getStruct()->name())); + return hashName(type.getStruct()->name()); else return type.getBuiltInTypeNameString(); } -TString TOutputGLSLBase::hashName(const TName &name) +TString TOutputGLSLBase::hashName(const TString &name) { - if (name.getString().empty()) - { - ASSERT(!name.isInternal()); - return name.getString(); - } - if (name.isInternal()) - { - // TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is - // done in the HLSL output, but that requires fairly complex changes elsewhere in the code - // as well. - // We need to use a prefix that is reserved in WebGL in order to guarantee that the internal - // names don't conflict with user-defined names from WebGL. - return "webgl_angle_" + name.getString(); - } - if (mHashFunction == nullptr) - { - return name.getString(); - } - NameMap::const_iterator it = mNameMap.find(name.getString().c_str()); + if (mHashFunction == NULL || name.empty()) + return name; + NameMap::const_iterator it = mNameMap.find(name.c_str()); if (it != mNameMap.end()) return it->second.c_str(); - TString hashedName = TIntermTraverser::hash(name.getString(), mHashFunction); - mNameMap[name.getString().c_str()] = hashedName.c_str(); + TString hashedName = TIntermTraverser::hash(name, mHashFunction); + mNameMap[name.c_str()] = hashedName.c_str(); return hashedName; } -TString TOutputGLSLBase::hashVariableName(const TName &name) +TString TOutputGLSLBase::hashVariableName(const TString &name) { - if (mSymbolTable.findBuiltIn(name.getString(), mShaderVersion) != NULL) - return name.getString(); + if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL) + return name; return hashName(name); } @@ -1287,16 +1185,9 @@ TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName) if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main") return translateTextureFunction(name); if (mangledName.isInternal()) - { - // Internal function names are outputted as-is - they may refer to functions manually added - // to the output shader source that are not included in the AST at all. return name; - } else - { - TName nameObj(name); - return hashName(nameObj); - } + return hashName(name); } bool TOutputGLSLBase::structDeclared(const TStructure *structure) const @@ -1314,14 +1205,14 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) { TInfoSinkBase &out = objSink(); - out << "struct " << hashName(TName(structure->name())) << "{\n"; + out << "struct " << hashName(structure->name()) << "{\n"; const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); + out << getTypeName(*field->type()) << " " << hashName(field->name()); if (field->type()->isArray()) out << arrayBrackets(*field->type()); out << ";\n"; @@ -1382,19 +1273,17 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc { TInfoSinkBase &out = objSink(); - out << hashName(TName(interfaceBlock->name())) << "{\n"; + out << hashName(interfaceBlock->name()) << "{\n"; const TFieldList &fields = interfaceBlock->fields(); for (size_t i = 0; i < fields.size(); ++i) { const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; - out << getTypeName(*field->type()) << " " << hashName(TName(field->name())); + out << getTypeName(*field->type()) << " " << hashName(field->name()); if (field->type()->isArray()) out << arrayBrackets(*field->type()); out << ";\n"; } out << "}"; } - -} // namespace sh |