diff --git a/Test/300block.frag b/Test/300block.frag new file mode 100644 index 0000000000000000000000000000000000000000..989fee3c6c9211953598ceddf2b1e6999f7d83cc --- /dev/null +++ b/Test/300block.frag @@ -0,0 +1,38 @@ +#version 300 es + +struct S { + vec4 u; + uvec4 v; + isampler3D sampler; + vec3 w; + struct T1 { // ERROR + int a; + } t; +}; + +uniform S s; + +uniform fooBlock { + uvec4 bv; + mat2 bm2; + isampler2D sampler; // ERROR + struct T2 { // ERROR + int a; + } t; + S fbs; +}; + +uniform barBlock { + uvec4 nbv; + int ni; +} inst; + +uniform barBlockArray { + uvec4 nbv; + int ni; +} insts[4]; + +void main() +{ + texture(s.sampler, vec3(inst.ni, bv.y, insts[2].nbv.z)); +} diff --git a/Test/testlist b/Test/testlist index 23a03a554a5fe00d15ab5e77c0e92f92764968bf..355ce8ec7b59c84fd7a608633bdb45ad37ff7a73 100644 --- a/Test/testlist +++ b/Test/testlist @@ -27,6 +27,7 @@ comment.frag 300layout.vert 300layout.frag 300operations.frag +300block.frag 330.frag 330comp.frag constErrors.frag diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index e26ab4b39949527c6575dc3b4255e10782faf9c1..2466a7e11aade2bc01833c8cd85a1e9b05c7157c 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -392,7 +392,7 @@ typedef std::map<TTypeList*, TTypeList*>::const_iterator TStructureMapIterator; class TType { public: POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) : + explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) : basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0), structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) @@ -416,7 +416,10 @@ public: basicType(p.basicType), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes), structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) { - sampler = p.sampler; + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); qualifier = p.qualifier; if (p.userDef) { structure = p.userDef->getStruct(); @@ -494,6 +497,21 @@ public: arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level } + // Merge type from parent, where a parentType is at the beginning of a declaration, + // establishing some charastics for all subsequent names, while this type + // is on the individual names. + void mergeType(const TPublicType& parentType) + { + // arrayness is currently the only child aspect that has to be preserved + setElementType(parentType.basicType, parentType.vectorSize, parentType.matrixCols, parentType.matrixRows, parentType.userDef); + qualifier = parentType.qualifier; + sampler = parentType.sampler; + if (parentType.arraySizes) + setArraySizes(parentType.arraySizes); + if (parentType.userDef) + setTypeName(parentType.userDef->getTypeName()); + } + TType* clone(const TStructureMap& remapper) { TType *newType = new TType(); diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 52538fdc88d7277679d1c33498142f38f56746ac..0e39ca8c9e52df2707d7d86fe9fd0413048ae79b 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -676,7 +676,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif break; } - // Do non in/out error checks + // Do non-in/out error checks if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform")) return true; @@ -1517,7 +1517,7 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b return; } - // check for qualifiers that don't belong within a block + // 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(); if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && @@ -1531,6 +1531,12 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b recover(); } } + + TBasicType basicType = typeList[member].type->getBasicType(); + if (basicType == EbtSampler) { + error(line, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), ""); + recover(); + } } // Make default block qualification, and adjust the member qualifications @@ -1546,6 +1552,8 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b // Build and add the interface block as a new type named blockName TType blockType(&typeList, blockName, publicType.qualifier.storage); + if (arraySizes) + blockType.setArraySizes(arraySizes); blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking; TVariable* userTypeDef = new TVariable(&blockName, blockType, true); if (! symbolTable.insert(*userTypeDef)) { diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 02ae2019f75e44b5ad5c097cf7dee244dcdcb972..5e077ca85560172e37e7012f0ec3689c1ddd920b 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -1600,11 +1600,11 @@ fully_specified_type parseContext.recover(); $2.arraySizes = 0; } + + if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true)) + parseContext.recover(); $$ = $2; - $$.qualifier = $1.qualifier; - if ($$.qualifier.precision == EpqNone) - $$.qualifier.precision = $2.qualifier.precision; if (! $$.qualifier.isInterpolation() && parseContext.language == EShLangFragment) $$.qualifier.smooth = true; @@ -2560,6 +2560,10 @@ precision_qualifier struct_specifier : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE { // TODO: semantics: check for qualifiers that don't belong in a struct + + // TODO: semantics: check that this is not nested inside a block or structure + // parseContext.error($1.line, "cannot nest a block or structure definitions", $1.userDef->getTypeName().c_str(), ""); + TType* structure = new TType($4, *$2.string); TVariable* userTypeDef = new TVariable($2.string, *structure, true); if (! parseContext.symbolTable.insert(*userTypeDef)) { @@ -2608,17 +2612,8 @@ struct_declaration if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) { parseContext.recover(); } - for (unsigned int i = 0; i < $$->size(); ++i) { - // - // Careful not to replace already know aspects of type, like array-ness - // - (*$$)[i].type->setElementType($1.basicType, $1.vectorSize, $1.matrixCols, $1.matrixRows, $1.userDef); - - if ($1.arraySizes) - (*$$)[i].type->setArraySizes($1.arraySizes); - if ($1.userDef) - (*$$)[i].type->setTypeName($1.userDef->getTypeName()); - } + for (unsigned int i = 0; i < $$->size(); ++i) + (*$$)[i].type->mergeType($1); } | type_qualifier type_specifier struct_declarator_list SEMICOLON { if ($2.arraySizes) { @@ -2632,17 +2627,8 @@ struct_declaration parseContext.recover(); if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true)) parseContext.recover(); - for (unsigned int i = 0; i < $$->size(); ++i) { - // - // Careful not to replace already know aspects of type, like array-ness - // - (*$$)[i].type->setElementType($2.basicType, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef); - (*$$)[i].type->getQualifier() = $2.qualifier; - if ($2.arraySizes) - (*$$)[i].type->setArraySizes($2.arraySizes); - if ($2.userDef) - (*$$)[i].type->setTypeName($2.userDef->getTypeName()); - } + for (unsigned int i = 0; i < $$->size(); ++i) + (*$$)[i].type->mergeType($2); } ; diff --git a/glslang/MachineIndependent/preprocessor/cpp.c b/glslang/MachineIndependent/preprocessor/cpp.c index 8f24b662055bb92e27fe7a5a42c9df06ffbb91c7..efa77bc3a1b4c6eb62dd5d3f6336a20471155198 100644 --- a/glslang/MachineIndependent/preprocessor/cpp.c +++ b/glslang/MachineIndependent/preprocessor/cpp.c @@ -982,7 +982,7 @@ static int macro_scan(InputSrc *inInput, yystypepp * yylvalpp) // return a zero, for scanning a macro that was never defined static int zero_scan(InputSrc *inInput, yystypepp * yylvalpp) { - MacroInputSrc* in = (MacroInputSrc*)inInput; //?? need to free this? + MacroInputSrc* in = (MacroInputSrc*)inInput; strcpy(yylvalpp->symbol_name, "0"); yylvalpp->sc_int = 0;