diff --git a/Test/array.frag b/Test/array.frag index 63d5f4c0a..a7b96a441 100644 --- a/Test/array.frag +++ b/Test/array.frag @@ -102,11 +102,12 @@ void foo3() } int[] i = int[](); // ERROR, need constructor arguments -float emptyA[]; -float b = vec4(emptyA); // ERROR, array can't be a constructor argument -uniform sampler2D s2d[]; - -void foo4() -{ - s2d[a]; // ERROR, can't variably index unsized array -} +float emptyA[]; +float b = vec4(emptyA); // ERROR, array can't be a constructor argument +uniform sampler2D s2d[]; + +void foo4() +{ + s2d[a]; // ERROR, can't variably index unsized array + float local[] = gUnusedUnsized; // ERROR, can initialize with runtime-sized array +} diff --git a/Test/baseResults/array.frag.out b/Test/baseResults/array.frag.out index fadccf5b8..2af9f27f7 100644 --- a/Test/baseResults/array.frag.out +++ b/Test/baseResults/array.frag.out @@ -27,7 +27,8 @@ ERROR: 0:104: '=' : cannot convert from ' const float' to ' global unsized 1-el ERROR: 0:106: 'constructor' : array argument must be sized ERROR: 0:111: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier ERROR: 0:111: 'variable indexing sampler array' : not supported with this profile: none -ERROR: 28 compilation errors. No code generated. +ERROR: 0:112: '[]' : array initializer must be sized +ERROR: 29 compilation errors. No code generated. Shader version: 130 @@ -272,6 +273,10 @@ ERROR: node is still EOpNull! 0:111 indirect index ( temp sampler2D) 0:111 's2d' ( uniform runtime-sized array of sampler2D) 0:111 'a' ( uniform int) +0:112 Sequence +0:112 move second child to first child ( temp unsized 1-element array of float) +0:112 'local' ( temp unsized 1-element array of float) +0:112 'gUnusedUnsized' ( global unsized 1-element array of float) 0:? Linker Objects 0:? 'gu' ( global runtime-sized array of float) 0:? 'g4' ( global 4-element array of float) diff --git a/Test/baseResults/runtimeArray.vert.out b/Test/baseResults/runtimeArray.vert.out index 839c5bd9a..5ba399291 100755 --- a/Test/baseResults/runtimeArray.vert.out +++ b/Test/baseResults/runtimeArray.vert.out @@ -31,7 +31,8 @@ ERROR: 0:104: 'variable index' : required extension not requested: GL_EXT_nonuni ERROR: 0:105: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier ERROR: 0:106: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier ERROR: 0:107: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier -ERROR: 26 compilation errors. No code generated. +ERROR: 0:109: '[]' : array initializer must be sized +ERROR: 27 compilation errors. No code generated. Shader version: 450 @@ -311,6 +312,13 @@ ERROR: node is still EOpNull! 0:107 indirect index (layout( binding=9 r32f) temp imageBuffer) 0:107 'storageTexelBuffer' (layout( binding=9 r32f) uniform runtime-sized array of imageBuffer) 0:107 'i' ( global int) +0:109 Sequence +0:109 move second child to first child ( temp unsized 1-element array of float) +0:109 'local' ( temp unsized 1-element array of float) +0:109 b: direct index for structure (layout( column_major shared) uniform runtime-sized array of float) +0:109 'ubuf' (layout( column_major shared) uniform block{layout( column_major shared) uniform runtime-sized array of int a, layout( column_major shared) uniform runtime-sized array of float b}) +0:109 Constant: +0:109 1 (const int) 0:? Linker Objects 0:? 'buf' (layout( column_major shared) buffer block{layout( column_major shared) buffer runtime-sized array of int a, layout( column_major shared) buffer runtime-sized array of float b}) 0:? 'ubuf' (layout( column_major shared) uniform block{layout( column_major shared) uniform runtime-sized array of int a, layout( column_major shared) uniform runtime-sized array of float b}) @@ -611,6 +619,13 @@ ERROR: node is still EOpNull! 0:107 indirect index (layout( binding=9 r32f) temp imageBuffer) 0:107 'storageTexelBuffer' (layout( binding=9 r32f) uniform runtime-sized array of imageBuffer) 0:107 'i' ( global int) +0:109 Sequence +0:109 move second child to first child ( temp 1-element array of float) +0:109 'local' ( temp 1-element array of float) +0:109 b: direct index for structure (layout( column_major shared) uniform runtime-sized array of float) +0:109 'ubuf' (layout( column_major shared) uniform block{layout( column_major shared) uniform runtime-sized array of int a, layout( column_major shared) uniform runtime-sized array of float b}) +0:109 Constant: +0:109 1 (const int) 0:? Linker Objects 0:? 'buf' (layout( column_major shared) buffer block{layout( column_major shared) buffer runtime-sized array of int a, layout( column_major shared) buffer runtime-sized array of float b}) 0:? 'ubuf' (layout( column_major shared) uniform block{layout( column_major shared) uniform runtime-sized array of int a, layout( column_major shared) uniform runtime-sized array of float b}) diff --git a/Test/runtimeArray.vert b/Test/runtimeArray.vert index 596143361..a5da4f419 100644 --- a/Test/runtimeArray.vert +++ b/Test/runtimeArray.vert @@ -105,4 +105,6 @@ void main() storageImage[i]; // ERROR, need extension uniformTexelBuffer[i]; // ERROR, need extension storageTexelBuffer[i]; // ERROR, need extension + + float local[] = ubuf.b; // ERROR, can initialize with runtime-sized array } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index bb088e5d4..4f81e215f 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -3135,7 +3135,8 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ } } -void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, bool initializer, bool lastMember) +void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, + const TIntermTyped* initializer, bool lastMember) { assert(arraySizes); @@ -3143,9 +3144,13 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua if (parsingBuiltins) return; - // always allow an initializer to set any unknown array sizes - if (initializer) + // initializer must be a sized array, in which case + // allow the initializer to set any unknown array sizes + if (initializer != nullptr) { + if (initializer->getType().isUnsizedArray()) + error(loc, "array initializer must be sized", "[]", ""); return; + } // No environment allows any non-outer-dimension to be implicitly sized if (arraySizes->isInnerUnsized()) { @@ -5390,7 +5395,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden // Declare the variable if (type.isArray()) { // Check that implicit sizing is only where allowed. - arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer != nullptr, false); + arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false); if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) declareArray(loc, identifier, type, symbol); @@ -5992,7 +5997,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con blockStageIoCheck(loc, currentBlockQualifier); blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); if (arraySizes != nullptr) { - arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false); + arraySizesCheck(loc, currentBlockQualifier, arraySizes, nullptr, false); arrayOfArrayVersionCheck(loc, arraySizes); if (arraySizes->getNumDims() > 1) requireProfile(loc, ~EEsProfile, "array-of-array of block"); @@ -6010,7 +6015,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); if (memberType.isArray()) - arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), false, member == typeList.size() - 1); + arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1); if (memberQualifier.hasOffset()) { if (spvVersion.spv == 0) { requireProfile(memberLoc, ~EEsProfile, "offset on block member"); diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 21779c710..dd8e30d20 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -340,7 +340,7 @@ public: bool arrayError(const TSourceLoc&, const TType&); void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); void structArrayCheck(const TSourceLoc&, const TType& structure); - void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, bool initializer, bool lastMember); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); void boolCheck(const TSourceLoc&, const TIntermTyped*);