diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp | 322 |
1 files changed, 242 insertions, 80 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 4bb6305d05..f048b050b7 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -5,7 +5,8 @@ // #include "compiler/translator/OutputGLSLBase.h" -#include "compiler/translator/compilerdebug.h" + +#include "common/debug.h" #include <cfloat> @@ -88,30 +89,46 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet( writeTriplet(visit, preString.c_str(), ", ", ")"); } +void TOutputGLSLBase::writeLayoutQualifier(const TType &type) +{ + if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn) + { + const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier(); + if (layoutQualifier.location >= 0) + { + TInfoSinkBase &out = objSink(); + out << "layout(location = " << layoutQualifier.location << ") "; + } + } +} + void TOutputGLSLBase::writeVariableType(const TType &type) { TInfoSinkBase &out = objSink(); + if (type.isInvariant()) + { + out << "invariant "; + } + if (type.getBasicType() == EbtInterfaceBlock) + { + TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + declareInterfaceBlockLayout(interfaceBlock); + } TQualifier qualifier = type.getQualifier(); if (qualifier != EvqTemporary && qualifier != EvqGlobal) { - if (mOutput == SH_GLSL_CORE_OUTPUT) + if (IsGLSL130OrNewer(mOutput)) { switch (qualifier) { case EvqAttribute: - out << "in" << " "; + out << "in "; break; case EvqVaryingIn: - out << "in" << " "; + out << "in "; break; case EvqVaryingOut: - out << "out" << " "; - break; - case EvqInvariantVaryingIn: - out << "invariant in" << " "; - break; - case EvqInvariantVaryingOut: - out << "invariant out" << " "; + out << "out "; break; default: out << type.getQualifierString() << " "; @@ -135,6 +152,11 @@ void TOutputGLSLBase::writeVariableType(const TType &type) mDeclaredStructs.insert(structure->uniqueId()); } } + else if (type.getBasicType() == EbtInterfaceBlock) + { + TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + declareInterfaceBlock(interfaceBlock); + } else { if (writeVariablePrecision(type.getPrecision())) @@ -167,8 +189,8 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) } } -const ConstantUnion *TOutputGLSLBase::writeConstantUnion( - const TType &type, const ConstantUnion *pConstUnion) +const TConstantUnion *TOutputGLSLBase::writeConstantUnion( + const TType &type, const TConstantUnion *pConstUnion) { TInfoSinkBase &out = objSink(); @@ -221,6 +243,28 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion( return pConstUnion; } +void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType) +{ + TInfoSinkBase &out = objSink(); + if (visit == PreVisit) + { + if (type.isArray()) + { + out << constructorBaseType; + out << arrayBrackets(type); + out << "("; + } + else + { + out << constructorBaseType << "("; + } + } + else + { + writeTriplet(visit, nullptr, ", ", ")"); + } +} + void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) { TInfoSinkBase &out = objSink(); @@ -352,6 +396,22 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) 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) { @@ -363,7 +423,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); ASSERT(element->getBasicType() == EbtInt); ASSERT(element->getNominalSize() == 1); - const ConstantUnion& data = element->getUnionArrayPointer()[0]; + const TConstantUnion& data = element->getUnionArrayPointer()[0]; ASSERT(data.getType() == EbtInt); switch (data.getIConst()) { @@ -722,7 +782,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; TInfoSinkBase &out = objSink(); - TString preString; bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); switch (node->getOp()) { @@ -756,8 +815,14 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpPrototype: // Function declaration. ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashFunctionName(node->getName()); + { + const TType &type = node->getType(); + writeVariableType(type); + if (type.isArray()) + out << arrayBrackets(type); + } + + out << " " << hashFunctionNameIfNeeded(node->getNameObj()); out << "("; writeFunctionParameters(*(node->getSequence())); @@ -768,8 +833,14 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpFunction: { // Function definition. ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashFunctionName(node->getName()); + { + 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 @@ -798,16 +869,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpFunctionCall: // Function call. if (visit == PreVisit) - out << hashFunctionName(node->getName()) << "("; - else if (visit == InVisit) - out << ", "; - else - out << ")"; - break; - case EOpInternalFunctionCall: - // Function call to an internal helper function. - if (visit == PreVisit) - out << node->getName() << "("; + out << hashFunctionNameIfNeeded(node->getNameObj()) << "("; else if (visit == InVisit) out << ", "; else @@ -827,6 +889,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { const TIntermSequence &sequence = *(node->getSequence()); const TIntermTyped *variable = sequence.front()->getAsTyped(); + writeLayoutQualifier(variable->getType()); writeVariableType(variable->getType()); out << " "; mDeclaringVariables = true; @@ -854,66 +917,88 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) visitChildren = false; break; case EOpConstructFloat: - writeTriplet(visit, "float(", NULL, ")"); + writeConstructorTriplet(visit, node->getType(), "float"); break; case EOpConstructVec2: - writeBuiltInFunctionTriplet(visit, "vec2(", false); + writeConstructorTriplet(visit, node->getType(), "vec2"); break; case EOpConstructVec3: - writeBuiltInFunctionTriplet(visit, "vec3(", false); + writeConstructorTriplet(visit, node->getType(), "vec3"); break; case EOpConstructVec4: - writeBuiltInFunctionTriplet(visit, "vec4(", false); + writeConstructorTriplet(visit, node->getType(), "vec4"); break; case EOpConstructBool: - writeTriplet(visit, "bool(", NULL, ")"); + writeConstructorTriplet(visit, node->getType(), "bool"); break; case EOpConstructBVec2: - writeBuiltInFunctionTriplet(visit, "bvec2(", false); + writeConstructorTriplet(visit, node->getType(), "bvec2"); break; case EOpConstructBVec3: - writeBuiltInFunctionTriplet(visit, "bvec3(", false); + writeConstructorTriplet(visit, node->getType(), "bvec3"); break; case EOpConstructBVec4: - writeBuiltInFunctionTriplet(visit, "bvec4(", false); + writeConstructorTriplet(visit, node->getType(), "bvec4"); break; case EOpConstructInt: - writeTriplet(visit, "int(", NULL, ")"); + writeConstructorTriplet(visit, node->getType(), "int"); break; case EOpConstructIVec2: - writeBuiltInFunctionTriplet(visit, "ivec2(", false); + writeConstructorTriplet(visit, node->getType(), "ivec2"); break; case EOpConstructIVec3: - writeBuiltInFunctionTriplet(visit, "ivec3(", false); + writeConstructorTriplet(visit, node->getType(), "ivec3"); break; case EOpConstructIVec4: - writeBuiltInFunctionTriplet(visit, "ivec4(", false); + writeConstructorTriplet(visit, node->getType(), "ivec4"); + break; + case EOpConstructUInt: + writeConstructorTriplet(visit, node->getType(), "uint"); + break; + case EOpConstructUVec2: + writeConstructorTriplet(visit, node->getType(), "uvec2"); + break; + case EOpConstructUVec3: + writeConstructorTriplet(visit, node->getType(), "uvec3"); + break; + case EOpConstructUVec4: + writeConstructorTriplet(visit, node->getType(), "uvec4"); break; case EOpConstructMat2: - writeBuiltInFunctionTriplet(visit, "mat2(", false); + writeConstructorTriplet(visit, node->getType(), "mat2"); + break; + case EOpConstructMat2x3: + writeConstructorTriplet(visit, node->getType(), "mat2x3"); + break; + case EOpConstructMat2x4: + writeConstructorTriplet(visit, node->getType(), "mat2x4"); + break; + case EOpConstructMat3x2: + writeConstructorTriplet(visit, node->getType(), "mat3x2"); break; case EOpConstructMat3: - writeBuiltInFunctionTriplet(visit, "mat3(", false); + writeConstructorTriplet(visit, node->getType(), "mat3"); + break; + case EOpConstructMat3x4: + writeConstructorTriplet(visit, node->getType(), "mat3x4"); + break; + case EOpConstructMat4x2: + writeConstructorTriplet(visit, node->getType(), "mat4x2"); + break; + case EOpConstructMat4x3: + writeConstructorTriplet(visit, node->getType(), "mat4x3"); break; case EOpConstructMat4: - writeBuiltInFunctionTriplet(visit, "mat4(", false); + writeConstructorTriplet(visit, node->getType(), "mat4"); break; case EOpConstructStruct: - if (visit == PreVisit) { const TType &type = node->getType(); ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getStruct()->name()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; + TString constructorName = hashName(type.getStruct()->name()); + writeConstructorTriplet(visit, node->getType(), constructorName.c_str()); + break; } - break; case EOpOuterProduct: writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction); @@ -1004,8 +1089,12 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) TInfoSinkBase &out = objSink(); incrementDepth(node); - // Loop header. + TLoopType loopType = node->getType(); + + // Only for loops can be unrolled + ASSERT(!node->getUnrollFlag() || loopType == ELoopFor); + if (loopType == ELoopFor) // for loop { if (!node->getUnrollFlag()) @@ -1022,6 +1111,8 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) if (node->getExpression()) node->getExpression()->traverse(this); out << ")\n"; + + visitCodeBlock(node->getBody()); } else { @@ -1034,6 +1125,16 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) out << "for (int " << name << " = 0; " << name << " < 1; " << "++" << name << ")\n"; + + out << "{\n"; + mLoopUnrollStack.push(node); + while (mLoopUnrollStack.satisfiesLoopCondition()) + { + visitCodeBlock(node->getBody()); + mLoopUnrollStack.step(); + } + mLoopUnrollStack.pop(); + out << "}\n"; } } else if (loopType == ELoopWhile) // while loop @@ -1042,39 +1143,22 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) ASSERT(node->getCondition() != NULL); node->getCondition()->traverse(this); out << ")\n"; + + visitCodeBlock(node->getBody()); } else // do-while loop { ASSERT(loopType == ELoopDoWhile); out << "do\n"; - } - // Loop body. - if (node->getUnrollFlag()) - { - out << "{\n"; - mLoopUnrollStack.push(node); - while (mLoopUnrollStack.satisfiesLoopCondition()) - { - visitCodeBlock(node->getBody()); - mLoopUnrollStack.step(); - } - mLoopUnrollStack.pop(); - out << "}\n"; - } - else - { visitCodeBlock(node->getBody()); - } - // Loop footer. - if (loopType == ELoopDoWhile) // do-while loop - { out << "while ("; ASSERT(node->getCondition() != NULL); node->getCondition()->traverse(this); out << ");\n"; } + decrementDepth(); // No need to visit children. They have been already processed in @@ -1129,6 +1213,10 @@ TString TOutputGLSLBase::getTypeName(const TType &type) { out << "mat"; out << type.getNominalSize(); + if (type.getSecondarySize() != type.getNominalSize()) + { + out << "x" << type.getSecondarySize(); + } } else if (type.isVector()) { @@ -1143,6 +1231,9 @@ TString TOutputGLSLBase::getTypeName(const TType &type) case EbtBool: out << "bvec"; break; + case EbtUInt: + out << "uvec"; + break; default: UNREACHABLE(); } @@ -1177,12 +1268,16 @@ TString TOutputGLSLBase::hashVariableName(const TString &name) return hashName(name); } -TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name) +TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName) { - TString name = TFunction::unmangleName(mangled_name); - if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main") + TString mangledStr = mangledName.getString(); + TString name = TFunction::unmangleName(mangledStr); + if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main") return translateTextureFunction(name); - return hashName(name); + if (mangledName.isInternal()) + return name; + else + return hashName(name); } bool TOutputGLSLBase::structDeclared(const TStructure *structure) const @@ -1215,3 +1310,70 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure) out << "}"; } +void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock) +{ + TInfoSinkBase &out = objSink(); + + out << "layout("; + + switch (interfaceBlock->blockStorage()) + { + case EbsUnspecified: + case EbsShared: + // Default block storage is shared. + out << "shared"; + break; + + case EbsPacked: + out << "packed"; + break; + + case EbsStd140: + out << "std140"; + break; + + default: + UNREACHABLE(); + break; + } + + out << ", "; + + switch (interfaceBlock->matrixPacking()) + { + case EmpUnspecified: + case EmpColumnMajor: + // Default matrix packing is column major. + out << "column_major"; + break; + + case EmpRowMajor: + out << "row_major"; + break; + + default: + UNREACHABLE(); + break; + } + + out << ") "; +} + +void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock) +{ + TInfoSinkBase &out = objSink(); + + 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(field->name()); + if (field->type()->isArray()) + out << arrayBrackets(*field->type()); + out << ";\n"; + } + out << "}"; +} |