diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index df8a1e1f5..81486ca55 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -3744,6 +3744,7 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n { assert(node.getQualifier().isConstant()); + // Handle front-end constants first (non-specialization constants). if (! node.getQualifier().specConstant) { // hand off to the non-spec-constant path assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); @@ -3754,31 +3755,35 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // We now know we have a specialization constant to build - if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) { - // this is a direct literal assigned to a layout(constant_id=) declaration - int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, true); - } else { - // gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants, - // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... - if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) - addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); - } - return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); - } else if (auto* sn = node.getAsSymbolNode()){ - return createSpvConstantFromConstSubTree(sn->getConstSubtree()); - } else { - spv::MissingFunctionality("Neither a front-end constant nor a spec constant."); - exit(1); - return spv::NoResult; + // gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants, + // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... + if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { + std::vector dimConstId; + for (int dim = 0; dim < 3; ++dim) { + bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); + dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); + if (specConst) + addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); + } + return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); + } + + // An AST node labelled as specialization constant should be a symbol node. + // Its initializer should either be a sub tree with constant nodes, or a constant union array. + if (auto* sn = node.getAsSymbolNode()) { + if (auto* sub_tree = sn->getConstSubtree()) { + return createSpvConstantFromConstSubTree(sub_tree); + } else if (auto* const_union_array = &sn->getConstArray()){ + int nextConst = 0; + return createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); } } + + // Neither a front-end constant node, nor a specialization constant node with constant union array or + // constant sub tree as initializer. + spv::MissingFunctionality("Neither a front-end constant nor a spec constant."); + exit(1); + return spv::NoResult; } // Use 'consts' as the flattened glslang source of scalar constants to recursively diff --git a/Test/baseResults/spv.specConstant.vert.out b/Test/baseResults/spv.specConstant.vert.out index 862dc19a8..dadab07c5 100644 --- a/Test/baseResults/spv.specConstant.vert.out +++ b/Test/baseResults/spv.specConstant.vert.out @@ -7,32 +7,35 @@ Linked vertex stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 72 +// Id's are bound by 81 Capability Shader Capability Float64 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Vertex 4 "main" 17 19 25 50 + EntryPoint Vertex 4 "main" 20 22 28 53 Source GLSL 400 Name 4 "main" Name 14 "foo(vf4[s1498];" Name 13 "p" - Name 17 "color" - Name 19 "ucol" - Name 25 "size" - Name 44 "param" - Name 50 "dupUcol" + Name 17 "builtin_spec_constant(" + Name 20 "color" + Name 22 "ucol" + Name 28 "size" + Name 47 "param" + Name 53 "dupUcol" + Name 76 "result" Decorate 9 SpecId 16 - Decorate 27 SpecId 17 - Decorate 31 SpecId 22 - Decorate 36 SpecId 19 - Decorate 37 SpecId 18 - Decorate 47 SpecId 116 - Decorate 57 SpecId 117 - Decorate 60 SpecId 122 - Decorate 64 SpecId 119 - Decorate 65 SpecId 118 + Decorate 30 SpecId 17 + Decorate 34 SpecId 22 + Decorate 39 SpecId 19 + Decorate 40 SpecId 18 + Decorate 50 SpecId 116 + Decorate 60 SpecId 117 + Decorate 63 SpecId 122 + Decorate 67 SpecId 119 + Decorate 68 SpecId 118 + Decorate 77 SpecId 24 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 @@ -42,83 +45,93 @@ Linked vertex stage: 10: TypeArray 7(fvec4) 9 11: TypePointer Function 10 12: TypeFunction 2 11(ptr) - 16: TypePointer Output 7(fvec4) - 17(color): 16(ptr) Variable Output - 18: TypePointer Input 10 - 19(ucol): 18(ptr) Variable Input - 20: 8(int) Constant 2 - 21: TypePointer Input 7(fvec4) - 24: TypePointer Output 8(int) - 25(size): 24(ptr) Variable Output - 26: TypeBool - 27: 26(bool) SpecConstantTrue - 30: TypeInt 32 0 - 31: 30(int) SpecConstant 2 - 35: TypeFloat 64 - 36: 35(float) SpecConstant 1413754136 1074340347 - 37: 6(float) SpecConstant 1078523331 - 47: 8(int) SpecConstant 12 - 48: TypeArray 7(fvec4) 47 - 49: TypePointer Input 48 - 50(dupUcol): 49(ptr) Variable Input - 57: 26(bool) SpecConstantTrue - 60: 30(int) SpecConstant 2 - 64: 35(float) SpecConstant 1413754136 1074340347 - 65: 6(float) SpecConstant 1078523331 + 16: TypeFunction 8(int) + 19: TypePointer Output 7(fvec4) + 20(color): 19(ptr) Variable Output + 21: TypePointer Input 10 + 22(ucol): 21(ptr) Variable Input + 23: 8(int) Constant 2 + 24: TypePointer Input 7(fvec4) + 27: TypePointer Output 8(int) + 28(size): 27(ptr) Variable Output + 29: TypeBool + 30: 29(bool) SpecConstantTrue + 33: TypeInt 32 0 + 34: 33(int) SpecConstant 2 + 38: TypeFloat 64 + 39: 38(float) SpecConstant 1413754136 1074340347 + 40: 6(float) SpecConstant 1078523331 + 50: 8(int) SpecConstant 12 + 51: TypeArray 7(fvec4) 50 + 52: TypePointer Input 51 + 53(dupUcol): 52(ptr) Variable Input + 60: 29(bool) SpecConstantTrue + 63: 33(int) SpecConstant 2 + 67: 38(float) SpecConstant 1413754136 1074340347 + 68: 6(float) SpecConstant 1078523331 + 75: TypePointer Function 8(int) + 77: 8(int) SpecConstant 8 4(main): 2 Function None 3 5: Label - 44(param): 11(ptr) Variable Function - 22: 21(ptr) AccessChain 19(ucol) 20 - 23: 7(fvec4) Load 22 - Store 17(color) 23 - Store 25(size) 9 - SelectionMerge 29 None - BranchConditional 27 28 29 - 28: Label - 32: 6(float) ConvertUToF 31 - 33: 7(fvec4) Load 17(color) - 34: 7(fvec4) VectorTimesScalar 33 32 - Store 17(color) 34 - Branch 29 - 29: Label - 38: 35(float) FConvert 37 - 39: 35(float) FDiv 36 38 - 40: 6(float) FConvert 39 - 41: 7(fvec4) Load 17(color) - 42: 7(fvec4) CompositeConstruct 40 40 40 40 - 43: 7(fvec4) FAdd 41 42 - Store 17(color) 43 - 45: 10 Load 19(ucol) - Store 44(param) 45 - 46: 2 FunctionCall 14(foo(vf4[s1498];) 44(param) + 47(param): 11(ptr) Variable Function + 25: 24(ptr) AccessChain 22(ucol) 23 + 26: 7(fvec4) Load 25 + Store 20(color) 26 + Store 28(size) 9 + SelectionMerge 32 None + BranchConditional 30 31 32 + 31: Label + 35: 6(float) ConvertUToF 34 + 36: 7(fvec4) Load 20(color) + 37: 7(fvec4) VectorTimesScalar 36 35 + Store 20(color) 37 + Branch 32 + 32: Label + 41: 38(float) FConvert 40 + 42: 38(float) FDiv 39 41 + 43: 6(float) FConvert 42 + 44: 7(fvec4) Load 20(color) + 45: 7(fvec4) CompositeConstruct 43 43 43 43 + 46: 7(fvec4) FAdd 44 45 + Store 20(color) 46 + 48: 10 Load 22(ucol) + Store 47(param) 48 + 49: 2 FunctionCall 14(foo(vf4[s1498];) 47(param) Return FunctionEnd 14(foo(vf4[s1498];): 2 Function None 12 13(p): 11(ptr) FunctionParameter 15: Label - 51: 21(ptr) AccessChain 50(dupUcol) 20 - 52: 7(fvec4) Load 51 - 53: 7(fvec4) Load 17(color) - 54: 7(fvec4) FAdd 53 52 - Store 17(color) 54 - 55: 8(int) Load 25(size) - 56: 8(int) IAdd 55 47 - Store 25(size) 56 - SelectionMerge 59 None - BranchConditional 57 58 59 - 58: Label - 61: 6(float) ConvertUToF 60 - 62: 7(fvec4) Load 17(color) - 63: 7(fvec4) VectorTimesScalar 62 61 - Store 17(color) 63 - Branch 59 - 59: Label - 66: 35(float) FConvert 65 - 67: 35(float) FDiv 64 66 - 68: 6(float) FConvert 67 - 69: 7(fvec4) Load 17(color) - 70: 7(fvec4) CompositeConstruct 68 68 68 68 - 71: 7(fvec4) FAdd 69 70 - Store 17(color) 71 + 54: 24(ptr) AccessChain 53(dupUcol) 23 + 55: 7(fvec4) Load 54 + 56: 7(fvec4) Load 20(color) + 57: 7(fvec4) FAdd 56 55 + Store 20(color) 57 + 58: 8(int) Load 28(size) + 59: 8(int) IAdd 58 50 + Store 28(size) 59 + SelectionMerge 62 None + BranchConditional 60 61 62 + 61: Label + 64: 6(float) ConvertUToF 63 + 65: 7(fvec4) Load 20(color) + 66: 7(fvec4) VectorTimesScalar 65 64 + Store 20(color) 66 + Branch 62 + 62: Label + 69: 38(float) FConvert 68 + 70: 38(float) FDiv 67 69 + 71: 6(float) FConvert 70 + 72: 7(fvec4) Load 20(color) + 73: 7(fvec4) CompositeConstruct 71 71 71 71 + 74: 7(fvec4) FAdd 72 73 + Store 20(color) 74 Return FunctionEnd +17(builtin_spec_constant(): 8(int) Function None 16 + 18: Label + 76(result): 75(ptr) Variable Function + Store 76(result) 77 + 78: 8(int) Load 76(result) + ReturnValue 78 + FunctionEnd diff --git a/Test/spv.specConstant.vert b/Test/spv.specConstant.vert index 0f9764d46..9813bf5fa 100644 --- a/Test/spv.specConstant.vert +++ b/Test/spv.specConstant.vert @@ -8,6 +8,8 @@ layout(constant_id = 18) const float spFloat = 3.14; layout(constant_id = 19) const double spDouble = 3.1415926535897932384626433832795; layout(constant_id = 22) const uint scale = 2; +layout(constant_id = 24) gl_MaxImageUnits; + out vec4 color; out int size; @@ -41,3 +43,9 @@ void foo(vec4 p[arraySize]) color *= dupScale; color += float(spDupDouble / spDupFloat); } + +int builtin_spec_constant() +{ + int result = gl_MaxImageUnits; + return result; +} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index d47a0ed47..945327df5 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -5714,6 +5714,10 @@ void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qua error(loc, "cannot change qualification after use", "invariant", ""); symbol->getWritableType().getQualifier().invariant = true; invariantCheck(loc, symbol->getType().getQualifier()); + } else if (qualifier.specConstant) { + symbol->getWritableType().getQualifier().makeSpecConstant(); + if (qualifier.hasSpecConstantId()) + symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; } else warn(loc, "unknown requalification", "", ""); }