From 457145ded5159754742e6810f04ad761e135e293 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 16 Oct 2013 04:08:21 +0000 Subject: [PATCH] Have block members use EvqVaryingIn rather than EvqIn, etc., confining the EvqIn-class of qualifier just to parameters and parse time (before it's known if something is a parameter). Also, have member error messages report their actual line, rather than the block's line. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23499 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/baseResults/300block.frag.out | 2 +- Test/baseResults/300layout.vert.out | 6 +- Test/baseResults/specExamples.frag.out | 10 ++-- glslang/Include/BaseTypes.h | 6 +- glslang/MachineIndependent/ParseHelper.cpp | 69 +++++++++++----------- glslang/MachineIndependent/ParseHelper.h | 7 ++- glslang/MachineIndependent/glslang.y | 39 +++++++----- 7 files changed, 75 insertions(+), 64 deletions(-) diff --git a/Test/baseResults/300block.frag.out b/Test/baseResults/300block.frag.out index adcc2737..18dedaf3 100644 --- a/Test/baseResults/300block.frag.out +++ b/Test/baseResults/300block.frag.out @@ -1,6 +1,6 @@ ERROR: 0:10: '' : cannot nest a structure definition inside a structure or block ERROR: 0:21: '' : cannot nest a structure definition inside a structure or block -ERROR: 0:17: 'sampler' : member of block cannot be a sampler type +ERROR: 0:20: 'sampler' : member of block cannot be a sampler type ERROR: 0:45: 'variable indexing block array' : not supported with this profile: es ERROR: 4 compilation errors. No code generated. diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out index 7f2d0ddf..fb1e04c5 100644 --- a/Test/baseResults/300layout.vert.out +++ b/Test/baseResults/300layout.vert.out @@ -3,10 +3,10 @@ ERROR: 0:8: 'in' : cannot be a structure or array ERROR: 0:8: 'vertex input arrays' : not supported with this profile: es ERROR: 0:12: 'badm4' : cannot specify matrix layout on a variable declaration ERROR: 0:12: 'badm4' : cannot specify packing on a variable declaration -ERROR: 0:15: 'badf' : member of uniform block cannot have an auxiliary or interpolation qualifier -ERROR: 0:15: 'badg' : member storage qualifier cannot contradict block storage qualifier +ERROR: 0:19: 'badf' : member of uniform block cannot have an auxiliary or interpolation qualifier +ERROR: 0:20: 'badg' : member storage qualifier cannot contradict block storage qualifier ERROR: 0:28: 'T3' : nameless block contains a member that already has a name at global scope -ERROR: 0:35: 'in/out block' : not supported with this profile: es +ERROR: 0:35: 'output block' : not supported with this profile: es ERROR: 0:39: 'badoutA' : can only use location layout qualifier on a vertex input or fragment output ERROR: 0:47: 'shared' : not supported with this profile: es ERROR: 0:47: 'shared' : not supported in this stage: vertex diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index 609a580a..09d4e86f 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -4,7 +4,7 @@ ERROR: 0:20: '' : numeric literal too big ERROR: 0:21: '' : hexidecimal literal too big ERROR: 0:37: 'view' : redefinition ERROR: 0:68: 'lightPosition' : redefinition -ERROR: 0:71: 'Atten' : member storage qualifier cannot contradict block storage qualifier +ERROR: 0:75: 'Atten' : member storage qualifier cannot contradict block storage qualifier ERROR: 0:87: 'Color' : redefinition ERROR: 0:92: 'origin_upper_left' : unrecognized layout identifier ERROR: 0:93: 'pixel_center_integer' : unrecognized layout identifier @@ -48,10 +48,10 @@ ERROR: 0:198: 'e' : redefinition ERROR: 0:217: '=' : cannot convert from 'const float' to 'unsized array of float' ERROR: 0:219: '=' : cannot convert from 'unsized array of float' to '5-element array of float' ERROR: 0:223: '=' : assigning non-constant to 'const float' -ERROR: 0:226: 'in' : only allowed at global scope -ERROR: 0:227: 'in' : only allowed at global scope -ERROR: 0:228: 'in' : only allowed at global scope -ERROR: 0:232: 'out' : only allowed at global scope +ERROR: 0:226: 'in' : not allowed in nested scope +ERROR: 0:227: 'in' : not allowed in nested scope +ERROR: 0:228: 'in' : not allowed in nested scope +ERROR: 0:232: 'out' : not allowed in nested scope ERROR: 53 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h index 0790a898..095ee236 100644 --- a/glslang/Include/BaseTypes.h +++ b/glslang/Include/BaseTypes.h @@ -69,10 +69,10 @@ enum TStorageQualifier { EvqVaryingOut, // pipeline ouput, read/write EvqUniform, // read only, shader with app EvqBuffer, // read only, shader with app - + // parameters - EvqIn, - EvqOut, + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter EvqInOut, EvqConstReadOnly, diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 6fb2c8d0..7b1c6569 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1219,10 +1219,10 @@ void TParseContext::integerCheck(TIntermTyped* node, const char* token) // Both test, and if necessary spit out an error, to see if we are currently // globally scoped. // -void TParseContext::globalCheck(TSourceLoc loc, bool global, const char* token) +void TParseContext::globalCheck(TSourceLoc loc, const char* token) { - if (! global) - error(loc, "only allowed at global scope", token, ""); + if (! symbolTable.atGlobalLevel()) + error(loc, "not allowed in nested scope", token, ""); } // @@ -1415,13 +1415,11 @@ bool TParseContext::samplerErrorCheck(TSourceLoc loc, const TPublicType& pType, return false; } -void TParseContext::globalQualifierFix(TSourceLoc loc, TQualifier& qualifier, const TPublicType& publicType) +// +// move from parameter/unknown qualifiers to pipeline in/out qualifiers +// +void TParseContext::pipeInOutFix(TSourceLoc loc, TQualifier& qualifier) { - if (! symbolTable.atGlobalLevel()) - return; - - // First, move from parameter qualifiers to shader in/out qualifiers - switch (qualifier.storage) { case EvqIn: profileRequires(loc, ENoProfile, 130, 0, "in for stage inputs"); @@ -1433,17 +1431,19 @@ void TParseContext::globalQualifierFix(TSourceLoc loc, TQualifier& qualifier, co profileRequires(loc, EEsProfile, 300, 0, "out for stage outputs"); qualifier.storage = EvqVaryingOut; break; - case EvqVaryingIn: - case EvqVaryingOut: - break; case EvqInOut: qualifier.storage = EvqVaryingIn; error(loc, "cannot use 'inout' at global scope", "", ""); - - return; + break; default: break; } +} + +void TParseContext::globalQualifierCheck(TSourceLoc loc, const TQualifier& qualifier, const TPublicType& publicType) +{ + if (! symbolTable.atGlobalLevel()) + return; // Do non-in/out error checks @@ -1895,7 +1895,7 @@ TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifi return 0; } -void TParseContext::paramCheck(TSourceLoc loc, TStorageQualifier qualifier, TType* type) +void TParseContext::paramCheck(TSourceLoc loc, const TStorageQualifier& qualifier, TType* type) { switch (qualifier) { case EvqConst: @@ -2110,7 +2110,6 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, error(loc, "there is no such layout identifier taking an assigned value", id.c_str(), ""); // TODO: semantics: error check: make sure locations are non-overlapping across the whole stage - // TODO: semantics: error check: if more than one fragment output, all must have a location // TODO: semantics: error check: output arrays can only be indexed with a constant (es 300) } @@ -2522,9 +2521,11 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* profileRequires(loc, EEsProfile, 300, 0, "uniform block"); profileRequires(loc, ENoProfile, 140, 0, "uniform block"); break; - case EvqIn: - case EvqOut: - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "in/out block"); + case EvqVaryingIn: + requireProfile(loc, ECoreProfile | ECompatibilityProfile, "input block"); + break; + case EvqVaryingOut: + requireProfile(loc, ECoreProfile | ECompatibilityProfile, "output block"); break; default: error(loc, "only uniform, in, or out interface blocks are supported", blockName->c_str(), ""); @@ -2533,28 +2534,30 @@ void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* arrayDimCheck(loc, arraySizes, 0); - // check for qualifiers and types that don't belong within a block + // fix and check for qualifiers and types that don't belong within a block for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier memberQualifier = typeList[member].type->getQualifier(); + TQualifier& memberQualifier = typeList[member].type->getQualifier(); + TSourceLoc memberLoc = typeList[member].loc; + pipeInOutFix(memberLoc, memberQualifier); if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockDefaults.storage) - error(loc, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), ""); + error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), ""); if ((currentBlockDefaults.storage == EvqUniform && memberQualifier.isInterpolation()) || memberQualifier.isAuxiliary()) - error(loc, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), ""); + error(memberLoc, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), ""); TBasicType basicType = typeList[member].type->getBasicType(); if (basicType == EbtSampler) - error(loc, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), ""); + error(memberLoc, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), ""); } // Make default block qualification, and adjust the member qualifications TQualifier defaultQualification; switch (currentBlockDefaults.storage) { - case EvqBuffer: defaultQualification = globalBufferDefaults; break; - case EvqUniform: defaultQualification = globalUniformDefaults; break; - case EvqIn: defaultQualification = globalInputDefaults; break; - case EvqOut: defaultQualification = globalOutputDefaults; break; - default: defaultQualification.clear(); break; + case EvqBuffer: defaultQualification = globalBufferDefaults; break; + case EvqUniform: defaultQualification = globalUniformDefaults; break; + case EvqVaryingIn: defaultQualification = globalInputDefaults; break; + case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; + default: defaultQualification.clear(); break; } mergeLayoutQualifiers(loc, defaultQualification, currentBlockDefaults); @@ -2650,11 +2653,11 @@ void TParseContext::updateQualifierDefaults(TQualifier qualifier) if (qualifier.layoutPacking != ElpNone) globalUniformDefaults.layoutPacking = qualifier.layoutPacking; break; - case EvqIn: + case EvqVaryingIn: if (qualifier.hasLocation()) globalInputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; break; - case EvqOut: + case EvqVaryingOut: if (qualifier.hasLocation()) globalOutputDefaults.layoutSlotLocation = qualifier.layoutSlotLocation; break; @@ -2674,8 +2677,8 @@ void TParseContext::updateQualifierDefaults(TSourceLoc loc, TQualifier qualifier switch (qualifier.storage) { case EvqUniform: - case EvqIn: - case EvqOut: + case EvqVaryingIn: + case EvqVaryingOut: break; default: error(loc, "standalone qualifier requires 'uniform', 'in', or 'out' storage qualification", "", ""); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 4e8d7d8c..d18e875b 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -92,7 +92,7 @@ public: bool lValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*); void constCheck(TIntermTyped* node, const char* token); void integerCheck(TIntermTyped* node, const char* token); - void globalCheck(TSourceLoc, bool global, const char* token); + void globalCheck(TSourceLoc, const char* token); bool constructorError(TSourceLoc, TIntermNode*, TFunction&, TOperator, TType&); void arraySizeCheck(TSourceLoc, TIntermTyped* expr, int& size); bool arrayQualifierError(TSourceLoc, const TQualifier&); @@ -104,7 +104,8 @@ public: void boolCheck(TSourceLoc, const TIntermTyped*); void boolCheck(TSourceLoc, const TPublicType&); bool samplerErrorCheck(TSourceLoc, const TPublicType& pType, const char* reason); - void globalQualifierFix(TSourceLoc, TQualifier&, const TPublicType&); + void pipeInOutFix(TSourceLoc, TQualifier&); + void globalQualifierCheck(TSourceLoc, const TQualifier&, const TPublicType&); bool structQualifierErrorCheck(TSourceLoc, const TPublicType& pType); void mergeQualifiers(TSourceLoc, TQualifier& dst, const TQualifier& src, bool force); void setDefaultPrecision(TSourceLoc, TPublicType&, TPrecisionQualifier); @@ -114,7 +115,7 @@ public: void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type); bool containsSampler(const TType& type); TSymbol* redeclareBuiltin(TSourceLoc, const TString&, bool& newDeclaration); - void paramCheck(TSourceLoc, TStorageQualifier qualifier, TType* type); + void paramCheck(TSourceLoc, const TStorageQualifier&, TType* type); void nestedBlockCheck(TSourceLoc); void nestedStructCheck(TSourceLoc); void arrayObjectCheck(TSourceLoc, const TType&, const char* op); diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index e9a4b37c..695b4f85 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -775,14 +775,17 @@ declaration $$ = 0; } | type_qualifier SEMICOLON { + parseContext.pipeInOutFix($1.loc, $1.qualifier); parseContext.updateQualifierDefaults($1.loc, $1.qualifier); $$ = 0; } | type_qualifier IDENTIFIER SEMICOLON { + parseContext.pipeInOutFix($1.loc, $1.qualifier); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); $$ = 0; } | type_qualifier IDENTIFIER identifier_list SEMICOLON { + parseContext.pipeInOutFix($1.loc, $1.qualifier); $3->push_back($2.string); parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); $$ = 0; @@ -793,6 +796,7 @@ block_structure : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { --parseContext.structNestingLevel; parseContext.blockName = $2.string; + parseContext.pipeInOutFix($1.loc, $1.qualifier); parseContext.currentBlockDefaults = $1.qualifier; $$.loc = $1.loc; $$.typeList = $5; @@ -1018,7 +1022,8 @@ fully_specified_type parseContext.precisionQualifierCheck($$.loc, $$); } | type_qualifier type_specifier { - parseContext.globalQualifierFix($1.loc, $1.qualifier, $2); + parseContext.pipeInOutFix($1.loc, $1.qualifier); + parseContext.globalQualifierCheck($1.loc, $1.qualifier, $2); if ($2.arraySizes) { parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type"); @@ -1052,21 +1057,21 @@ invariant_qualifier interpolation_qualifier : SMOOTH { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "smooth"); + parseContext.globalCheck($1.loc, "smooth"); parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "smooth"); parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "smooth"); $$.init($1.loc); $$.qualifier.smooth = true; } | FLAT { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "flat"); + parseContext.globalCheck($1.loc, "flat"); parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "flat"); parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "flat"); $$.init($1.loc); $$.qualifier.flat = true; } | NOPERSPECTIVE { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "noperspective"); + parseContext.globalCheck($1.loc, "noperspective"); parseContext.requireProfile($1.loc, ~EEsProfile, "noperspective"); parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "noperspective"); $$.init($1.loc); @@ -1164,7 +1169,7 @@ storage_qualifier parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "attribute"); parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "attribute"); - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "attribute"); + parseContext.globalCheck($1.loc, "attribute"); $$.init($1.loc); $$.qualifier.storage = EvqVaryingIn; @@ -1175,7 +1180,7 @@ storage_qualifier parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "varying"); parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "varying"); - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "varying"); + parseContext.globalCheck($1.loc, "varying"); $$.init($1.loc); if (parseContext.language == EShLangVertex) @@ -1184,44 +1189,46 @@ storage_qualifier $$.qualifier.storage = EvqVaryingIn; } | INOUT { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "out"); + parseContext.globalCheck($1.loc, "inout"); $$.init($1.loc); $$.qualifier.storage = EvqInOut; } | IN { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "in"); + parseContext.globalCheck($1.loc, "in"); $$.init($1.loc); + // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later $$.qualifier.storage = EvqIn; } | OUT { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "out"); + parseContext.globalCheck($1.loc, "out"); $$.init($1.loc); + // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later $$.qualifier.storage = EvqOut; } | CENTROID { parseContext.profileRequires($1.loc, ENoProfile, 120, 0, "centroid"); parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "centroid"); + parseContext.globalCheck($1.loc, "centroid"); $$.init($1.loc); $$.qualifier.centroid = true; } | PATCH { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "patch"); + parseContext.globalCheck($1.loc, "patch"); $$.init($1.loc); $$.qualifier.patch = true; } | SAMPLE { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "sample"); + parseContext.globalCheck($1.loc, "sample"); $$.init($1.loc); $$.qualifier.sample = true; } | UNIFORM { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "uniform"); + parseContext.globalCheck($1.loc, "uniform"); $$.init($1.loc); $$.qualifier.storage = EvqUniform; } | BUFFER { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "buffer"); + parseContext.globalCheck($1.loc, "buffer"); $$.init($1.loc); $$.qualifier.storage = EvqUniform; // TODO: 4.0 functionality: implement BUFFER } @@ -1253,12 +1260,12 @@ storage_qualifier $$.qualifier.writeonly = true; } | SUBROUTINE { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "subroutine"); + parseContext.globalCheck($1.loc, "subroutine"); $$.init($1.loc); $$.qualifier.storage = EvqUniform; } | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN { - parseContext.globalCheck($1.loc, parseContext.symbolTable.atGlobalLevel(), "subroutine"); + parseContext.globalCheck($1.loc, "subroutine"); $$.init($1.loc); $$.qualifier.storage = EvqUniform; // TODO: 4.0 semantics: subroutines