From 3fcb42cfa600c282f7cc5bf1680e5b2831b515b6 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Thu, 8 Jun 2017 12:26:49 -0600 Subject: [PATCH] GLSL: Fix #853: Only outer dimension of array can be specialization constant. --- Test/baseResults/vulkan.vert.out | 6 ++++- Test/vulkan.vert | 13 +++++++++++ glslang/Include/Types.h | 2 +- glslang/Include/arrays.h | 26 ++++++++++++---------- glslang/MachineIndependent/ParseHelper.cpp | 11 +++++---- glslang/MachineIndependent/ParseHelper.h | 2 +- 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/Test/baseResults/vulkan.vert.out b/Test/baseResults/vulkan.vert.out index 8d7a5ade..0b2ea530 100644 --- a/Test/baseResults/vulkan.vert.out +++ b/Test/baseResults/vulkan.vert.out @@ -22,7 +22,11 @@ ERROR: 0:32: 'initializer' : can't use with types containing arrays sized with a ERROR: 0:34: '=' : can't use with types containing arrays sized with a specialization constant ERROR: 0:35: '==' : can't use with types containing arrays sized with a specialization constant ERROR: 0:39: 'set' : cannot be used with push_constant -ERROR: 23 compilation errors. No code generated. +ERROR: 0:49: '[]' : only outermost dimension of an array of arrays can be a specialization constant +ERROR: 0:50: '[]' : only outermost dimension of an array of arrays can be a specialization constant +ERROR: 0:51: '[]' : only outermost dimension of an array of arrays can be a specialization constant +ERROR: 0:54: '[]' : only outermost dimension of an array of arrays can be a specialization constant +ERROR: 27 compilation errors. No code generated. SPIR-V is not generated for failed compile or link diff --git a/Test/vulkan.vert b/Test/vulkan.vert index b234c75b..a6dc8ad0 100644 --- a/Test/vulkan.vert +++ b/Test/vulkan.vert @@ -45,3 +45,16 @@ layout(set = 1, push_constant) uniform badpc { int a; } badpcI; // ERROR, no de #if VULKAN != 100 #error VULKAN should be 100 #endif + +float AofA0[2][arraySize]; // ERROR, only outer dimension +float AofA1[arraySize][arraySize]; // ERROR, only outer dimension +float AofA2[arraySize][2 + arraySize]; // ERROR, only outer dimension +float AofA3[arraySize][2]; + +out ban1 { // ERROR, only outer dimension + float f; +} bai1[2][arraySize]; + +out ban2 { + float f; +} bai2[arraySize][2]; diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 5eac73e0..fe4cccee 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -1460,7 +1460,7 @@ public: virtual bool containsSpecializationSize() const { - return contains([](const TType* t) { return t->isArray() && t->arraySizes->containsNode(); } ); + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); } // Array editing methods. Array descriptors can be shared across diff --git a/glslang/Include/arrays.h b/glslang/Include/arrays.h index b6b5e479..bc21c6c5 100644 --- a/glslang/Include/arrays.h +++ b/glslang/Include/arrays.h @@ -264,6 +264,20 @@ struct TArraySizes { return false; } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); } void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); } void dereference() { sizes.pop_front(); } @@ -288,18 +302,6 @@ struct TArraySizes { return true; } - // Returns true if any of the dimensions of the array is sized with a node - // instead of a front-end compile-time constant. - bool containsNode() - { - for (int d = 0; d < sizes.size(); ++d) { - if (sizes.getDimNode(d) != nullptr) - return true; - } - - return false; - } - bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; } bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index b3788d2e..e6d173cc 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -2958,7 +2958,7 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ } } -void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember) +void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember) { assert(arraySizes); @@ -2974,6 +2974,9 @@ void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& q if (arraySizes->isInnerImplicit()) error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", ""); + if (arraySizes->isInnerSpecialization()) + error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); + // desktop always allows outer-dimension-unsized variable arrays, if (profile != EEsProfile) return; @@ -5081,7 +5084,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden arrayDimMerge(type, arraySizes); // Check that implicit sizing is only where allowed. - arrayUnsizedCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false); + arraySizesCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false); if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) declareArray(loc, identifier, type, symbol); @@ -5633,7 +5636,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con blockStageIoCheck(loc, currentBlockQualifier); blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); if (arraySizes) { - arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes, false, false); + arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false); arrayDimCheck(loc, arraySizes, 0); if (arraySizes->getNumDims() > 1) requireProfile(loc, ~EEsProfile, "array-of-array of block"); @@ -5651,7 +5654,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()) - arrayUnsizedCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1); + arraySizesCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, 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 fb1f789c..4c5045c9 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -317,7 +317,7 @@ public: bool arrayError(const TSourceLoc&, const TType&); void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); void structArrayCheck(const TSourceLoc&, const TType& structure); - void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember); void arrayOfArrayVersionCheck(const TSourceLoc&); void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2); void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);