From bcd79fe5a301424ba7aed1a512edafbfdd43b0fe Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Wed, 10 Apr 2013 22:26:56 +0000 Subject: [PATCH] Implement default layout qualifiers at global and block levels with proper inheritance. Also add more error checking of qualifiers. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21107 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/300layout.vert | 6 ++ glslang/MachineIndependent/ParseHelper.cpp | 83 +++++++++++++++++----- glslang/MachineIndependent/ParseHelper.h | 4 +- glslang/MachineIndependent/glslang.y | 8 ++- glslang/MachineIndependent/intermOut.cpp | 4 +- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/Test/300layout.vert b/Test/300layout.vert index 60ef58514..7abbed31a 100644 --- a/Test/300layout.vert +++ b/Test/300layout.vert @@ -12,6 +12,8 @@ layout(std140) uniform Transform { // layout of this block is std140 mat4 M1; // row_major layout(column_major) mat4 M2; // column major mat3 N1; // row_major + centroid float badf; // ERROR + in float badg; // ERROR } tblock; uniform T2 { // layout of this block is shared @@ -26,6 +28,10 @@ layout(column_major) uniform T3 { // shared and column_major int b; // ERROR, redefinition (needs to be last member of block for testing, following members are skipped) }; +out badout { // ERROR + float f; +}; + void main() { pos = p * (tblock.M1 + tblock.M2 + M4 + M3 + t2m); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 3f8df1585..dc69bb92d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -70,6 +70,11 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E error(1, "INTERNAL ERROR", "unexpected language", ""); } } + + defaultGlobalQualification.clear(); + defaultGlobalQualification.layoutMatrix = ElmColumnMajor; + defaultGlobalQualification.layoutPacking = ElpShared; + defaultGlobalQualification.layoutSlotLocation = 0; } /////////////////////////////////////////////////////////////////////// @@ -750,7 +755,7 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const dst.qualifier.precision = src.qualifier.precision; // Layout qualifiers - mergeLayoutQualifiers(line, dst, src); + mergeLayoutQualifiers(line, dst.qualifier, src.qualifier); // other qualifiers #define MERGE_SINGLETON(field) bad |= dst.qualifier.field && src.qualifier.field; dst.qualifier.field |= src.qualifier.field; @@ -1133,16 +1138,16 @@ void TParseContext::setLayoutQualifier(int line, TPublicType& publicType, TStrin } // Merge any layout qualifier information from src into dst, leaving everything else in dst alone -void TParseContext::mergeLayoutQualifiers(int line, TPublicType& dst, const TPublicType& src) +void TParseContext::mergeLayoutQualifiers(int line, TQualifier& dst, const TQualifier& src) { - if (src.qualifier.layoutMatrix != ElmNone) - dst.qualifier.layoutMatrix = src.qualifier.layoutMatrix; + if (src.layoutMatrix != ElmNone) + dst.layoutMatrix = src.layoutMatrix; - if (src.qualifier.layoutPacking != ElpNone) - dst.qualifier.layoutPacking = src.qualifier.layoutPacking; + if (src.layoutPacking != ElpNone) + dst.layoutPacking = src.layoutPacking; - if (src.qualifier.hasLocation()) - dst.qualifier.layoutSlotLocation = src.qualifier.layoutSlotLocation; + if (src.hasLocation()) + dst.layoutSlotLocation = src.layoutSlotLocation; } ///////////////////////////////////////////////////////////////////////////////// @@ -1464,7 +1469,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ // // Do everything needed to add an interface block. // -void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes) +void TParseContext::addBlock(int line, TPublicType& publicType, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes) { // First, error checks @@ -1478,13 +1483,13 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl return; } - if (qualifier.basicType != EbtVoid) { + if (publicType.basicType != EbtVoid) { error(line, "interface blocks cannot be declared with a type", blockName.c_str(), ""); recover(); return; } - if (qualifier.qualifier.storage == EvqUniform) { + if (publicType.qualifier.storage == EvqUniform) { requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block"); profileRequires(line, EEsProfile, 300, 0, "uniform block"); } else { @@ -1494,9 +1499,36 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl return; } + // check for qualifiers that don't belong within a block + for (unsigned int member = 0; member < typeList.size(); ++member) { + TQualifier memberQualifier = typeList[member].type->getQualifier(); + if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && + memberQualifier.storage != publicType.qualifier.storage) { + error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), ""); + recover(); + } + if (publicType.qualifier.storage == EvqUniform) { + if (memberQualifier.isInterpolation() || memberQualifier.isAuxillary()) { + error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), ""); + recover(); + } + } + } + + // Make default block qualification, and adjust the member qualifications + + TQualifier defaultQualification = defaultGlobalQualification; + mergeLayoutQualifiers(line, defaultQualification, publicType.qualifier); + for (unsigned int member = 0; member < typeList.size(); ++member) { + TQualifier memberQualification = defaultQualification; + mergeLayoutQualifiers(line, memberQualification, typeList[member].type->getQualifier()); + typeList[member].type->getQualifier() = memberQualification; + } + // Build and add the interface block as a new type named blockName - TType blockType(&typeList, blockName, qualifier.qualifier.storage); + TType blockType(&typeList, blockName, publicType.qualifier.storage); + blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking; TVariable* userTypeDef = new TVariable(&blockName, blockType, true); if (! symbolTable.insert(*userTypeDef)) { error(line, "redefinition", blockName.c_str(), "block name"); @@ -1505,11 +1537,6 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl return; } - // TODO: semantics: check for qualifiers that don't belong within a block - for (unsigned int member = 0; member < typeList.size(); ++member) { - //printf("%s: %s\n", typeList[member].type->getFieldName().c_str(), typeList[member].type->getCompleteString().c_str()); - } - // Add the variable, as anonymous or named instanceName // make an anonymous variable if no name was provided @@ -1528,6 +1555,28 @@ void TParseContext::addBlock(int line, TPublicType& qualifier, const TString& bl } } +void TParseContext::updateDefaults(int line, const TPublicType& publicType, const TString* id) +{ + bool cantHaveId = false; + TQualifier qualifier = publicType.qualifier; + + if (qualifier.storage == EvqUniform) { + if (qualifier.layoutMatrix != ElmNone) { + cantHaveId = true; + defaultGlobalQualification.layoutMatrix = qualifier.layoutMatrix; + } + if (qualifier.layoutPacking != ElpNone) { + cantHaveId = true; + defaultGlobalQualification.layoutPacking = qualifier.layoutPacking; + } + } + + if (cantHaveId && id) { + error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), ""); + recover(); + } +} + // // This function returns the tree representation for the vector field(s) being accessed from contant vector. // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index d0d189e56..69504130d 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -91,6 +91,7 @@ struct TParseContext { struct TPragma contextPragma; TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TQualifier defaultGlobalQualification; TString HashErrMsg; bool AfterEOF; @@ -132,7 +133,7 @@ struct TParseContext { void setLayoutQualifier(int line, TPublicType&, TString&); void setLayoutQualifier(int line, TPublicType&, TString&, int); - void mergeLayoutQualifiers(int line, TPublicType& dest, const TPublicType& src); + void mergeLayoutQualifiers(int line, TQualifier& dest, const TQualifier& src); const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, @@ -141,6 +142,7 @@ struct TParseContext { TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset); void addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0); + void updateDefaults(int line, const TPublicType&, const TString* id); TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc); TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc); TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line); diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 954e5bd24..5ac46d723 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -234,7 +234,7 @@ variable_identifier unionArray->setUConst(anon->getMemberNumber()); TIntermTyped* constNode = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.line); - $$ = parseContext.intermediate.addIndex(EOpIndexDirect, container, constNode, $1.line); + $$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, container, constNode, $1.line); $$->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); } else { const TVariable* variable = symbol ? symbol->getAsVariable() : 0; @@ -1494,6 +1494,7 @@ single_declaration : fully_specified_type { $$.type = $1; $$.intermAggregate = 0; + parseContext.updateDefaults($1.line, $$.type, 0); } | fully_specified_type IDENTIFIER { $$.intermAggregate = 0; @@ -1504,6 +1505,8 @@ single_declaration if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type)) parseContext.recover(); + + parseContext.updateDefaults($2.line, $$.type, $2.string); } | fully_specified_type IDENTIFIER array_specifier { $$.intermAggregate = 0; @@ -1520,6 +1523,7 @@ single_declaration if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable)) parseContext.recover(); } + parseContext.updateDefaults($2.line, $$.type, $2.string); } | fully_specified_type IDENTIFIER array_specifier EQUAL initializer { $$.intermAggregate = 0; @@ -1647,7 +1651,7 @@ layout_qualifier_id_list } | layout_qualifier_id_list COMMA layout_qualifier_id { $$ = $1; - parseContext.mergeLayoutQualifiers($2.line, $$, $3); + parseContext.mergeLayoutQualifiers($2.line, $$.qualifier, $3.qualifier); } layout_qualifier_id diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp index 982608463..ace815422 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -119,7 +119,9 @@ bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it case EOpIndexDirect: out.debug << "direct index"; break; case EOpIndexIndirect: out.debug << "indirect index"; break; - case EOpIndexDirectStruct: out.debug << "direct index for structure"; break; + case EOpIndexDirectStruct: + out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getUnionArrayPointer()->getIConst()].type->getFieldName(); + out.debug << ": direct index for structure"; break; case EOpVectorSwizzle: out.debug << "vector swizzle"; break; case EOpAdd: out.debug << "add"; break; -- GitLab