diff --git a/Test/baseResults/spv.meshShaderBuiltins.mesh.out b/Test/baseResults/spv.meshShaderBuiltins.mesh.out index 8090f7bf..38d363bb 100644 --- a/Test/baseResults/spv.meshShaderBuiltins.mesh.out +++ b/Test/baseResults/spv.meshShaderBuiltins.mesh.out @@ -1,7 +1,7 @@ spv.meshShaderBuiltins.mesh // Module Version 10000 // Generated by (magic number): 80007 -// Id's are bound by 146 +// Id's are bound by 148 Capability ClipDistance Capability CullDistance @@ -14,7 +14,7 @@ spv.meshShaderBuiltins.mesh Extension "SPV_NV_viewport_array2" 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint MeshNV 4 "main" 11 17 34 88 128 139 143 + EntryPoint MeshNV 4 "main" 11 17 34 88 129 142 146 ExecutionMode 4 LocalSize 32 1 1 ExecutionMode 4 OutputVertices 81 ExecutionMode 4 OutputPrimitivesNV 32 @@ -43,9 +43,9 @@ spv.meshShaderBuiltins.mesh MemberName 84(gl_MeshPerPrimitiveNV) 4 "gl_LayerPerViewNV" MemberName 84(gl_MeshPerPrimitiveNV) 5 "gl_ViewportMaskPerViewNV" Name 88 "gl_MeshPrimitivesNV" - Name 128 "gl_PrimitiveIndicesNV" - Name 139 "gl_DrawID" - Name 143 "gl_PrimitiveCountNV" + Name 129 "gl_PrimitiveIndicesNV" + Name 142 "gl_DrawID" + Name 146 "gl_PrimitiveCountNV" Decorate 11(gl_LocalInvocationID) BuiltIn LocalInvocationId Decorate 17(gl_WorkGroupID) BuiltIn WorkgroupId MemberDecorate 30(gl_MeshPerVertexNV) 0 BuiltIn Position @@ -74,10 +74,10 @@ spv.meshShaderBuiltins.mesh MemberDecorate 84(gl_MeshPerPrimitiveNV) 5 PerViewNV MemberDecorate 84(gl_MeshPerPrimitiveNV) 5 BuiltIn ViewportMaskPerViewNV Decorate 84(gl_MeshPerPrimitiveNV) Block - Decorate 128(gl_PrimitiveIndicesNV) BuiltIn PrimitiveIndicesNV - Decorate 139(gl_DrawID) BuiltIn DrawIndex - Decorate 143(gl_PrimitiveCountNV) BuiltIn PrimitiveCountNV - Decorate 145 BuiltIn WorkgroupSize + Decorate 129(gl_PrimitiveIndicesNV) BuiltIn PrimitiveIndicesNV + Decorate 142(gl_DrawID) BuiltIn DrawIndex + Decorate 146(gl_PrimitiveCountNV) BuiltIn PrimitiveCountNV + Decorate 147 BuiltIn WorkgroupSize 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -130,17 +130,18 @@ spv.meshShaderBuiltins.mesh 94: 36(int) Constant 7 97: 36(int) Constant 8 100: 36(int) Constant 9 - 126: TypeArray 6(int) 31 - 127: TypePointer Output 126 -128(gl_PrimitiveIndicesNV): 127(ptr) Variable Output - 129: 6(int) Constant 257 - 130: TypePointer Output 6(int) - 138: TypePointer Input 36(int) - 139(gl_DrawID): 138(ptr) Variable Input - 142: 6(int) Constant 16909060 -143(gl_PrimitiveCountNV): 130(ptr) Variable Output - 144: 6(int) Constant 96 - 145: 9(ivec3) ConstantComposite 85 27 27 + 126: 6(int) Constant 96 + 127: TypeArray 6(int) 126 + 128: TypePointer Output 127 +129(gl_PrimitiveIndicesNV): 128(ptr) Variable Output + 130: 6(int) Constant 257 + 131: TypePointer Output 6(int) + 133: 36(int) Constant 95 + 141: TypePointer Input 36(int) + 142(gl_DrawID): 141(ptr) Variable Input + 145: 6(int) Constant 16909060 +146(gl_PrimitiveCountNV): 131(ptr) Variable Output + 147: 9(ivec3) ConstantComposite 85 27 27 4(main): 2 Function None 3 5: Label 8(iid): 7(ptr) Variable Function @@ -239,19 +240,21 @@ spv.meshShaderBuiltins.mesh Store 125 124 MemoryBarrier 27 55 ControlBarrier 56 56 55 - 131: 130(ptr) AccessChain 128(gl_PrimitiveIndicesNV) 37 - Store 131 129 - 132: 6(int) Load 16(gid) - 133: 6(int) Load 16(gid) - 134: 6(int) ISub 133 27 - 135: 130(ptr) AccessChain 128(gl_PrimitiveIndicesNV) 134 - 136: 6(int) Load 135 - 137: 130(ptr) AccessChain 128(gl_PrimitiveIndicesNV) 132 - Store 137 136 - 140: 36(int) Load 139(gl_DrawID) - 141: 6(int) Bitcast 140 - 142: 141 WritePackedPrimitiveIndices4x8NV - Store 143(gl_PrimitiveCountNV) 144 + 132: 131(ptr) AccessChain 129(gl_PrimitiveIndicesNV) 37 + Store 132 130 + 134: 131(ptr) AccessChain 129(gl_PrimitiveIndicesNV) 133 + Store 134 56 + 135: 6(int) Load 16(gid) + 136: 6(int) Load 16(gid) + 137: 6(int) ISub 136 27 + 138: 131(ptr) AccessChain 129(gl_PrimitiveIndicesNV) 137 + 139: 6(int) Load 138 + 140: 131(ptr) AccessChain 129(gl_PrimitiveIndicesNV) 135 + Store 140 139 + 143: 36(int) Load 142(gl_DrawID) + 144: 6(int) Bitcast 143 + 145: 144 WritePackedPrimitiveIndices4x8NV + Store 146(gl_PrimitiveCountNV) 126 MemoryBarrier 27 55 ControlBarrier 56 56 55 Return diff --git a/Test/baseResults/spv.meshShaderRedeclBuiltins.mesh.out b/Test/baseResults/spv.meshShaderRedeclBuiltins.mesh.out index f4491c0e..4afbef9f 100644 --- a/Test/baseResults/spv.meshShaderRedeclBuiltins.mesh.out +++ b/Test/baseResults/spv.meshShaderRedeclBuiltins.mesh.out @@ -1,7 +1,7 @@ spv.meshShaderRedeclBuiltins.mesh // Module Version 10000 // Generated by (magic number): 80007 -// Id's are bound by 120 +// Id's are bound by 129 Capability ClipDistance Capability CullDistance @@ -12,7 +12,7 @@ spv.meshShaderRedeclBuiltins.mesh Extension "SPV_NV_viewport_array2" 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint MeshNV 4 "main" 11 17 28 81 + EntryPoint MeshNV 4 "main" 11 17 28 81 122 127 ExecutionMode 4 LocalSize 32 1 1 ExecutionMode 4 OutputVertices 81 ExecutionMode 4 OutputPrimitivesNV 32 @@ -36,6 +36,8 @@ spv.meshShaderRedeclBuiltins.mesh MemberName 77(gl_MeshPerPrimitiveNV) 2 "gl_ViewportIndex" MemberName 77(gl_MeshPerPrimitiveNV) 3 "gl_ViewportMask" Name 81 "gl_MeshPrimitivesNV" + Name 122 "gl_PrimitiveIndicesNV" + Name 127 "gl_PrimitiveCountNV" Decorate 11(gl_LocalInvocationID) BuiltIn LocalInvocationId Decorate 17(gl_WorkGroupID) BuiltIn WorkgroupId MemberDecorate 24(gl_MeshPerVertexNV) 0 BuiltIn Position @@ -52,7 +54,9 @@ spv.meshShaderRedeclBuiltins.mesh MemberDecorate 77(gl_MeshPerPrimitiveNV) 3 PerPrimitiveNV MemberDecorate 77(gl_MeshPerPrimitiveNV) 3 BuiltIn ViewportMaskNV Decorate 77(gl_MeshPerPrimitiveNV) Block - Decorate 119 BuiltIn WorkgroupSize + Decorate 122(gl_PrimitiveIndicesNV) BuiltIn PrimitiveIndicesNV + Decorate 127(gl_PrimitiveCountNV) BuiltIn PrimitiveCountNV + Decorate 128 BuiltIn WorkgroupSize 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 0 @@ -98,7 +102,14 @@ spv.meshShaderRedeclBuiltins.mesh 87: 30(int) Constant 7 90: 30(int) Constant 8 93: 30(int) Constant 9 - 119: 9(ivec3) ConstantComposite 78 49 49 + 119: 6(int) Constant 96 + 120: TypeArray 6(int) 119 + 121: TypePointer Output 120 +122(gl_PrimitiveIndicesNV): 121(ptr) Variable Output + 123: TypePointer Output 6(int) + 125: 30(int) Constant 95 +127(gl_PrimitiveCountNV): 123(ptr) Variable Output + 128: 9(ivec3) ConstantComposite 78 49 49 4(main): 2 Function None 3 5: Label 8(iid): 7(ptr) Variable Function @@ -197,5 +208,10 @@ spv.meshShaderRedeclBuiltins.mesh Store 118 117 MemoryBarrier 49 50 ControlBarrier 51 51 50 + 124: 123(ptr) AccessChain 122(gl_PrimitiveIndicesNV) 31 + Store 124 49 + 126: 123(ptr) AccessChain 122(gl_PrimitiveIndicesNV) 125 + Store 126 51 + Store 127(gl_PrimitiveCountNV) 119 Return FunctionEnd diff --git a/Test/spv.meshShaderBuiltins.mesh b/Test/spv.meshShaderBuiltins.mesh index 8adff3d8..0240a173 100644 --- a/Test/spv.meshShaderBuiltins.mesh +++ b/Test/spv.meshShaderBuiltins.mesh @@ -50,8 +50,9 @@ void main() BARRIER(); - // should truncate 257 -> 1 - gl_PrimitiveIndicesNV[0] = 257; + // check bound limits + gl_PrimitiveIndicesNV[0] = 257; // should truncate 257 -> 1 + gl_PrimitiveIndicesNV[(MAX_PRIM * 3) - 1] = 2; gl_PrimitiveIndicesNV[gid] = gl_PrimitiveIndicesNV[gid-1]; // writes 4 indices at offset gl_DrawID diff --git a/Test/spv.meshShaderRedeclBuiltins.mesh b/Test/spv.meshShaderRedeclBuiltins.mesh index 38107b29..1b19a751 100644 --- a/Test/spv.meshShaderRedeclBuiltins.mesh +++ b/Test/spv.meshShaderRedeclBuiltins.mesh @@ -22,14 +22,16 @@ out gl_MeshPerVertexNV { float gl_PointSize; float gl_ClipDistance[4]; float gl_CullDistance[4]; -} gl_MeshVerticesNV[]; +} gl_MeshVerticesNV[MAX_VER]; // explicitly sized to MAX_VER perprimitiveNV out gl_MeshPerPrimitiveNV { int gl_PrimitiveID; int gl_Layer; int gl_ViewportIndex; int gl_ViewportMask[]; -} gl_MeshPrimitivesNV[]; +} gl_MeshPrimitivesNV[]; // implicitly sized to MAX_PRIM + +out uint gl_PrimitiveIndicesNV[MAX_PRIM*3]; // explicitly sized to MAX_PRIM * 3 void main() { @@ -63,4 +65,9 @@ void main() gl_MeshPrimitivesNV[iid+1].gl_ViewportMask[0] = gl_MeshPrimitivesNV[iid].gl_ViewportMask[0]; BARRIER(); + + // check bound limits + gl_PrimitiveIndicesNV[0] = 1; + gl_PrimitiveIndicesNV[(MAX_PRIM * 3) - 1] = 2; + gl_PrimitiveCountNV = MAX_PRIM * 3; } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 6e386589..cf40baa1 100755 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -572,7 +572,7 @@ void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TInterm // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) if (symbolNode->getType().isUnsizedArray()) { - int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier().isPerPrimitive()); + int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier()); if (newSize > 0) symbolNode->getWritableType().changeOuterArraySize(newSize); } @@ -586,59 +586,80 @@ void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TInterm // Types without an array size will be given one. // Types already having a size that is wrong will get an error. // -void TParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly, bool isPerPrimitive) +void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, bool tailOnly) { - int requiredSize = getIoArrayImplicitSize(isPerPrimitive); - if (requiredSize == 0) - return; + int requiredSize = 0; + TString featureString; + size_t listSize = ioArraySymbolResizeList.size(); + size_t i = 0; - const char* feature; - if (language == EShLangGeometry) - feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl + // If tailOnly = true, only check the last array symbol in the list. + if (tailOnly) { + i = listSize - 1; + } + for (bool firstIteration = true; i < listSize; ++i) { + TType &type = ioArraySymbolResizeList[i]->getWritableType(); + + // As I/O array sizes don't change, fetch requiredSize only once, + // except for mesh shaders which could have different I/O array sizes based on type qualifiers. + if (firstIteration #ifdef NV_EXTENSIONS - || language == EShLangFragment + || (language == EShLangMeshNV) #endif ) + { + requiredSize = getIoArrayImplicitSize(type.getQualifier(), &featureString); + if (requiredSize == 0) + break; + firstIteration = false; + } - feature = "vertices"; -#ifdef NV_EXTENSIONS - else if (language == EShLangMeshNV) { - feature = isPerPrimitive ? "max_primitives" : "max_vertices"; - } -#endif - else - feature = "unknown"; - - if (tailOnly) { - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName()); - return; + checkIoArrayConsistency(loc, requiredSize, featureString.c_str(), type, + ioArraySymbolResizeList[i]->getName()); } - - for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i) - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName()); } -int TParseContext::getIoArrayImplicitSize(bool isPerPrimitive) const +int TParseContext::getIoArrayImplicitSize(const TQualifier &qualifier, TString *featureString) const { - if (language == EShLangGeometry) - return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl) - return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; + int expectedSize = 0; + TString str = "unknown"; + unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; + + if (language == EShLangGeometry) { + expectedSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); + str = TQualifier::getGeometryString(intermediate.getInputPrimitive()); + } + else if (language == EShLangTessControl) { + expectedSize = maxVertices; + str = "vertices"; + } #ifdef NV_EXTENSIONS - else if (language == EShLangFragment) - return 3; //Number of vertices for Fragment shader is always three. + else if (language == EShLangFragment) { + // Number of vertices for Fragment shader is always three. + expectedSize = 3; + str = "vertices"; + } else if (language == EShLangMeshNV) { - if (isPerPrimitive) { - return intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0; - } else { - return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; + unsigned int maxPrimitives = + intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0; + if (qualifier.builtIn == EbvPrimitiveIndicesNV) { + expectedSize = maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive()); + str = "max_primitives*"; + str += TQualifier::getGeometryString(intermediate.getOutputPrimitive()); + } + else if (qualifier.isPerPrimitive()) { + expectedSize = maxPrimitives; + str = "max_primitives"; + } + else { + expectedSize = maxVertices; + str = "max_vertices"; } } #endif - - else - return 0; + if (featureString) + *featureString = str; + return expectedSize; } void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) @@ -1386,7 +1407,7 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction #endif ) { - length = getIoArrayImplicitSize(type.getQualifier().isPerPrimitive()); + length = getIoArrayImplicitSize(type.getQualifier()); } } if (length == 0) { @@ -3730,7 +3751,7 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie if (! symbolTable.atBuiltInLevel()) { if (isIoResizeArray(type)) { ioArraySymbolResizeList.push_back(symbol); - checkIoArraysConsistency(loc, true, type.getQualifier().isPerPrimitive()); + checkIoArraysConsistency(loc, true); } else fixIoArraySize(loc, symbol->getWritableType()); } @@ -3783,7 +3804,7 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie existingType.updateArraySizes(type); if (isIoResizeArray(type)) - checkIoArraysConsistency(loc, false, type.getQualifier().isPerPrimitive()); + checkIoArraysConsistency(loc); } // Policy and error check for needing a runtime sized array. @@ -3939,6 +3960,7 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS #ifdef NV_EXTENSIONS identifier == "gl_SampleMask" || identifier == "gl_Layer" || + identifier == "gl_PrimitiveIndicesNV" || #endif identifier == "gl_TexCoord") { @@ -4018,7 +4040,11 @@ TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TS error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); } } - else if (identifier == "gl_FragStencilRefARB") { + else if ( +#ifdef NV_EXTENSIONS + identifier == "gl_PrimitiveIndicesNV" || +#endif + identifier == "gl_FragStencilRefARB") { if (qualifier.hasLayout()) error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); if (qualifier.storage != EvqVaryingOut) @@ -4270,7 +4296,7 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT // Tracking for implicit sizing of array if (isIoResizeArray(block->getType())) { ioArraySymbolResizeList.push_back(block); - checkIoArraysConsistency(loc, true, block->getType().getQualifier().isPerPrimitive()); + checkIoArraysConsistency(loc, true); } else if (block->getType().isArray()) fixIoArraySize(loc, block->getWritableType()); @@ -7102,7 +7128,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con // fix up if (isIoResizeArray(blockType)) { ioArraySymbolResizeList.push_back(&variable); - checkIoArraysConsistency(loc, true, blockType.getQualifier().isPerPrimitive()); + checkIoArraysConsistency(loc, true); } else fixIoArraySize(loc, variable.getWritableType()); @@ -7685,6 +7711,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con else error(loc, "can only apply to 'in'", "derivative_group_linearNV", ""); } + // Check mesh out array sizes, once all the necessary out qualifiers are defined. + if ((language == EShLangMeshNV) && + (intermediate.getVertices() != TQualifier::layoutNotSet) && + (intermediate.getPrimitives() != TQualifier::layoutNotSet) && + (intermediate.getOutputPrimitive() != ElgNone)) + { + checkIoArraysConsistency(loc); + } #endif const TQualifier& qualifier = publicType.qualifier; @@ -7835,3 +7869,4 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre } } // end namespace glslang + diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 5b7d430c..f61345dc 100755 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -299,8 +299,8 @@ public: void fixIoArraySize(const TSourceLoc&, TType&); void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); - void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false, bool isPerPrimitive = false); - int getIoArrayImplicitSize(bool isPerPrimitive = false) const; + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);