diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 39f3b8bc..9d4dc590 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -151,7 +151,6 @@ protected: void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); spv::Id createSpvConstant(const glslang::TIntermTyped&); spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); - spv::Id createSpvConstantFromConstSubTree(glslang::TIntermTyped* subTree); bool isTrivialLeaf(const glslang::TIntermTyped* node); bool isTrivial(const glslang::TIntermTyped* node); spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); @@ -1113,6 +1112,10 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) { + SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + if (node->getType().getQualifier().isSpecConstant()) + spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); + spv::Id result = spv::NoResult; // try texturing @@ -3814,7 +3817,11 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n // 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); + // Traverse the constant constructor sub tree like generating normal run-time instructions. + // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard + // will set the builder into spec constant op instruction generating mode. + sub_tree->traverse(this); + return accessChainLoad(sub_tree->getType()); } else if (auto* const_union_array = &sn->getConstArray()){ int nextConst = 0; return createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); @@ -3910,68 +3917,6 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla return builder.makeCompositeConstant(typeId, spvConsts); } -// Create constant ID from const initializer sub tree. -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree( - glslang::TIntermTyped* subTree) -{ - const glslang::TType& glslangType = subTree->getType(); - spv::Id typeId = convertGlslangToSpvType(glslangType); - bool is_spec_const = subTree->getType().getQualifier().isSpecConstant(); - if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) { - // Aggregate node, we should generate OpConstantComposite or - // OpSpecConstantComposite instruction. - - std::vector const_constituents; - for (auto NI = an->getSequence().begin(); NI != an->getSequence().end(); - NI++) { - const_constituents.push_back( - createSpvConstantFromConstSubTree((*NI)->getAsTyped())); - } - // Note that constructors are aggregate nodes, so expressions like: - // float x = float(y) will become an aggregate node. If 'x' is declared - // as a constant, the aggregate node representing 'float(y)' will be - // processed here. - if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) || - builder.isAggregateType(typeId)) { - return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const); - } else { - assert(builder.isScalarType(typeId) && const_constituents.size() == 1); - return const_constituents.front(); - } - - } else if (glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) { - // Binary operation node, we should generate OpSpecConstantOp - // This case should only happen when Specialization Constants are involved. - bn->traverse(this); - return accessChainLoad(bn->getType()); - - } else if (glslang::TIntermUnary* un = subTree->getAsUnaryNode()) { - // Unary operation node, similar to binary operation node, should only - // happen when specialization constants are involved. - un->traverse(this); - return accessChainLoad(un->getType()); - - } else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) { - // ConstantUnion node, should redirect to - // createSpvConstantFromConstUnionArray - int nextConst = 0; - return createSpvConstantFromConstUnionArray( - glslangType, cn->getConstArray(), nextConst, is_spec_const); - - } else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) { - // Symbol node. Call getSymbolId(). This should cover both cases 1) the - // symbol has already been assigned an ID, 2) need a new ID for this - // symbol. - return getSymbolId(sn); - - } else { - spv::MissingFunctionality( - "createSpvConstantFromConstSubTree() not covered TIntermTyped* const " - "initializer subtree."); - return spv::NoResult; - } -} - // Return true if the node is a constant or symbol whose reading has no // non-trivial observable cost or effect. bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 7896deb4..bbb30c35 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -47,6 +47,7 @@ #include #include +#include #include "SpvBuilder.h" @@ -645,6 +646,21 @@ bool Builder::isConstantOpCode(Op opcode) const } } +// Return true if consuming 'opcode' means consuming a specialization constant. +bool Builder::isSpecConstantOpCode(Op opcode) const +{ + switch (opcode) { + case OpSpecConstantTrue: + case OpSpecConstantFalse: + case OpSpecConstant: + case OpSpecConstantComposite: + case OpSpecConstantOp: + return true; + default: + return false; + } +} + Id Builder::makeBoolConstant(bool b, bool specConstant) { Id typeId = makeBoolType(); @@ -1345,13 +1361,15 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) Instruction* smear = nullptr; if (generatingOpCodeForSpecConst) { auto members = std::vector(numComponents, scalar); - // 'scalar' can not be spec constant here. All spec constant involved - // promotion is done in createSpvConstantFromConstUnionArray(). This - // 'if' branch is only accessed when 'scalar' is used in the def-chain - // of other vector type spec constants. In such cases, all the - // instructions needed to promote 'scalar' to a vector type constants - // should be added at module level. - auto result_id = makeCompositeConstant(vectorType, members, false); + // Sometime even in spec-constant-op mode, the temporary vector created by + // promoting a scalar might not be a spec constant. This should depend on + // the scalar. + // e.g.: + // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; + // In such cases, the temporary vector created from a_front_end_const_scalar + // is not a spec constant vector, even though the binary operation node is marked + // as 'specConstant' and we are in spec-constant-op mode. + auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); smear = module.getInstruction(result_id); } else { smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); @@ -1714,6 +1732,20 @@ Id Builder::createCompositeConstruct(Id typeId, std::vector& constituents) { assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); + if (generatingOpCodeForSpecConst) { + // Sometime, even in spec-constant-op mode, the constant composite to be + // constructed may not be a specialization constant. + // e.g.: + // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); + // The first column vector should be a spec constant one, as a_spec_const is a spec constant. + // The second column vector should NOT be spec constant, as it does not contain any spec constants. + // To handle such cases, we check the constituents of the constant vector to determine whether this + // vector should be created as a spec constant. + return makeCompositeConstant(typeId, constituents, + std::any_of(constituents.begin(), constituents.end(), + [&](spv::Id id) { return isSpecConstant(id); })); + } + Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); for (int c = 0; c < (int)constituents.size(); ++c) op->addIdOperand(constituents[c]); diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 62f6775e..661bb115 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -147,8 +147,10 @@ public: bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } diff --git a/Test/baseResults/spv.specConstantComposite.vert.out b/Test/baseResults/spv.specConstantComposite.vert.out index 5e2dfa4a..ac101f28 100644 --- a/Test/baseResults/spv.specConstantComposite.vert.out +++ b/Test/baseResults/spv.specConstantComposite.vert.out @@ -7,13 +7,13 @@ Linked vertex stage: // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 106 +// Id's are bound by 119 Capability Shader Capability Float64 1: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 - EntryPoint Vertex 4 "main" 27 105 + EntryPoint Vertex 4 "main" 27 118 Source GLSL 450 Name 4 "main" Name 6 "refer_primary_spec_const(" @@ -23,23 +23,23 @@ Linked vertex stage: Name 16 "refer_spec_const_array_length(" Name 18 "declare_spec_const_in_func(" Name 27 "color" - Name 41 "flat_struct" - MemberName 41(flat_struct) 0 "i" - MemberName 41(flat_struct) 1 "f" - MemberName 41(flat_struct) 2 "d" - MemberName 41(flat_struct) 3 "b" - Name 42 "nesting_struct" - MemberName 42(nesting_struct) 0 "nested" - MemberName 42(nesting_struct) 1 "v" - MemberName 42(nesting_struct) 2 "i" + Name 42 "flat_struct" + MemberName 42(flat_struct) 0 "i" + MemberName 42(flat_struct) 1 "f" + MemberName 42(flat_struct) 2 "d" + MemberName 42(flat_struct) 3 "b" + Name 44 "nesting_struct" + MemberName 44(nesting_struct) 0 "nested" + MemberName 44(nesting_struct) 1 "v" + MemberName 44(nesting_struct) 2 "i" Name 72 "indexable" Name 76 "indexable" Name 83 "len" - Name 105 "global_vec4_array_with_spec_length" + Name 118 "global_vec4_array_with_spec_length" Decorate 21 SpecId 203 Decorate 28 SpecId 200 Decorate 32 SpecId 201 - Decorate 43 SpecId 202 + Decorate 41 SpecId 202 2: TypeVoid 3: TypeFunction 2 14: TypeInt 32 1 @@ -56,40 +56,53 @@ Linked vertex stage: 36: 24(float) Constant 1133908460 37: 25(fvec4) SpecConstantComposite 32 32 36 36 40: TypeFloat 64 - 41(flat_struct): TypeStruct 14(int) 24(float) 40(float) 20(bool) -42(nesting_struct): TypeStruct 41(flat_struct) 25(fvec4) 14(int) - 43: 40(float) SpecConstant 1413754136 1074340347 - 44:41(flat_struct) SpecConstantComposite 28 32 43 21 - 45:42(nesting_struct) SpecConstantComposite 44 33 28 + 41: 40(float) SpecConstant 1413754136 1074340347 + 42(flat_struct): TypeStruct 14(int) 24(float) 40(float) 20(bool) + 43:42(flat_struct) SpecConstantComposite 28 32 41 21 +44(nesting_struct): TypeStruct 42(flat_struct) 25(fvec4) 14(int) + 45:44(nesting_struct) SpecConstantComposite 43 33 28 46: 14(int) Constant 2 51: TypeInt 32 0 52: 51(int) Constant 0 - 57: 51(int) Constant 5 - 58: TypeArray 24(float) 57 - 59: 24(float) Constant 1065353216 - 60: 24(float) Constant 1073741824 - 61: 24(float) Constant 1077936128 - 62: 58 SpecConstantComposite 32 32 59 60 61 + 57: 24(float) Constant 1065353216 + 58: 24(float) Constant 1073741824 + 59: 24(float) Constant 1077936128 + 60: 51(int) Constant 5 + 61: TypeArray 24(float) 60 + 62: 61 SpecConstantComposite 32 32 57 58 59 63: 14(int) Constant 1 - 68: TypeArray 14(int) 57 - 69: 14(int) Constant 30 - 70: 68 SpecConstantComposite 28 28 63 46 69 - 71: TypePointer Function 68 + 68: 14(int) Constant 30 + 69: TypeArray 14(int) 60 + 70: 69 SpecConstantComposite 28 28 63 46 68 + 71: TypePointer Function 69 73: TypePointer Function 14(int) 87: 24(float) Constant 1106321080 - 88:41(flat_struct) SpecConstantComposite 69 87 43 21 + 88:42(flat_struct) SpecConstantComposite 68 87 41 21 89: 14(int) Constant 10 - 90:42(nesting_struct) SpecConstantComposite 88 37 89 + 90:44(nesting_struct) SpecConstantComposite 88 37 89 96: 20(bool) ConstantFalse - 97:41(flat_struct) SpecConstantComposite 28 32 43 96 + 97:42(flat_struct) SpecConstantComposite 28 32 41 96 98: 24(float) Constant 1036831949 99: 25(fvec4) ConstantComposite 98 98 98 98 - 100:42(nesting_struct) SpecConstantComposite 97 99 28 - 101: 14(int) Constant 3000 - 102:42(nesting_struct) SpecConstantComposite 88 37 101 - 103: TypeArray 25(fvec4) 28 - 104: TypePointer Input 103 -105(global_vec4_array_with_spec_length): 104(ptr) Variable Input + 100:44(nesting_struct) SpecConstantComposite 97 99 28 + 101: 25(fvec4) SpecConstantComposite 32 32 32 32 + 102: 24(float) Constant 1066192077 + 103: 24(float) Constant 1074580685 + 104: 24(float) Constant 1079194419 + 105: TypeVector 24(float) 3 + 106: TypeMatrix 105(fvec3) 2 + 107: 24(float) Constant 0 + 108: 105(fvec3) SpecConstantComposite 32 32 32 + 109: 105(fvec3) ConstantComposite 102 103 104 + 110: 106 SpecConstantComposite 108 109 + 111: 105(fvec3) SpecConstantComposite 32 107 107 + 112: 105(fvec3) SpecConstantComposite 107 32 107 + 113: 106 SpecConstantComposite 111 112 + 114: 14(int) Constant 3000 + 115:44(nesting_struct) SpecConstantComposite 88 37 114 + 116: TypeArray 25(fvec4) 28 + 117: TypePointer Input 116 +118(global_vec4_array_with_spec_length): 117(ptr) Variable Input 4(main): 2 Function None 3 5: Label Return diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out index eedbea5c..39de987d 100644 --- a/Test/baseResults/spv.specConstantOperations.vert.out +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -84,55 +84,55 @@ Linked vertex stage: 82: 22(bool) SpecConstantOp 177 19 43 83: 22(bool) SpecConstantOp 170 42 42 84: 22(bool) SpecConstantOp 173 19 43 - 85: TypeVector 6(int) 4 - 86: 6(int) Constant 30 - 87: 85(ivec4) SpecConstantComposite 74 86 19 19 - 88: TypeVector 41(int) 4 - 89: 41(int) Constant 4294967295 - 90: 41(int) Constant 4294967294 - 91: 88(ivec4) SpecConstantComposite 42 42 89 90 - 92: TypeVector 39(float) 4 - 93: 39(float) Constant 1067450368 - 94: 92(fvec4) SpecConstantComposite 40 93 40 93 + 85: 6(int) Constant 30 + 86: TypeVector 6(int) 4 + 87: 86(ivec4) SpecConstantComposite 74 85 19 19 + 88: 41(int) Constant 4294967295 + 89: 41(int) Constant 4294967294 + 90: TypeVector 41(int) 4 + 91: 90(ivec4) SpecConstantComposite 42 42 88 89 + 92: 39(float) Constant 1067450368 + 93: TypeVector 39(float) 4 + 94: 93(fvec4) SpecConstantComposite 40 92 40 92 95: TypeVector 22(bool) 4 - 96: 88(ivec4) ConstantComposite 44 44 44 44 + 96: 90(ivec4) ConstantComposite 44 44 44 44 97: 95(bvec4) SpecConstantOp 171 87 96 98: 95(bvec4) SpecConstantOp 171 91 96 - 99: 85(ivec4) ConstantComposite 12 12 12 12 - 100: 85(ivec4) ConstantComposite 32 32 32 32 - 101: 85(ivec4) SpecConstantOp 169 97 100 99 - 102: 88(ivec4) ConstantComposite 48 48 48 48 - 103: 88(ivec4) SpecConstantOp 169 97 102 96 - 104: 88(ivec4) SpecConstantOp 128 87 96 - 105: 85(ivec4) SpecConstantOp 128 91 96 - 106: 85(ivec4) SpecConstantOp 200 87 - 107: 85(ivec4) SpecConstantOp 126 87 - 108: 85(ivec4) ConstantComposite 20 20 20 20 - 109: 85(ivec4) SpecConstantOp 128 87 108 - 110: 85(ivec4) SpecConstantOp 128 87 108 - 111: 85(ivec4) ConstantComposite 56 56 56 56 - 112: 85(ivec4) SpecConstantOp 130 110 111 - 113: 85(ivec4) ConstantComposite 58 58 58 58 - 114: 85(ivec4) SpecConstantOp 130 112 113 - 115: 85(ivec4) SpecConstantOp 132 87 108 - 116: 85(ivec4) ConstantComposite 63 63 63 63 - 117: 85(ivec4) SpecConstantOp 135 115 116 - 118: 85(ivec4) SpecConstantOp 139 87 113 - 119: 85(ivec4) ConstantComposite 72 72 72 72 - 120: 85(ivec4) SpecConstantOp 195 87 119 - 121: 85(ivec4) SpecConstantOp 196 87 108 + 99: 86(ivec4) ConstantComposite 12 12 12 12 + 100: 86(ivec4) ConstantComposite 32 32 32 32 + 101: 86(ivec4) SpecConstantOp 169 97 100 99 + 102: 90(ivec4) ConstantComposite 48 48 48 48 + 103: 90(ivec4) SpecConstantOp 169 97 102 96 + 104: 90(ivec4) SpecConstantOp 128 87 96 + 105: 86(ivec4) SpecConstantOp 128 91 96 + 106: 86(ivec4) SpecConstantOp 200 87 + 107: 86(ivec4) SpecConstantOp 126 87 + 108: 86(ivec4) ConstantComposite 20 20 20 20 + 109: 86(ivec4) SpecConstantOp 128 87 108 + 110: 86(ivec4) SpecConstantOp 128 87 108 + 111: 86(ivec4) ConstantComposite 56 56 56 56 + 112: 86(ivec4) SpecConstantOp 130 110 111 + 113: 86(ivec4) ConstantComposite 58 58 58 58 + 114: 86(ivec4) SpecConstantOp 130 112 113 + 115: 86(ivec4) SpecConstantOp 132 87 108 + 116: 86(ivec4) ConstantComposite 63 63 63 63 + 117: 86(ivec4) SpecConstantOp 135 115 116 + 118: 86(ivec4) SpecConstantOp 139 87 113 + 119: 86(ivec4) ConstantComposite 72 72 72 72 + 120: 86(ivec4) SpecConstantOp 195 87 119 + 121: 86(ivec4) SpecConstantOp 196 87 108 122: 6(int) Constant 1024 - 123: 85(ivec4) ConstantComposite 122 122 122 122 - 124: 85(ivec4) SpecConstantOp 197 87 123 + 123: 86(ivec4) ConstantComposite 122 122 122 122 + 124: 86(ivec4) SpecConstantOp 197 87 123 125: 41(int) Constant 2048 - 126: 88(ivec4) ConstantComposite 125 125 125 125 - 127: 88(ivec4) SpecConstantOp 198 91 126 + 126: 90(ivec4) ConstantComposite 125 125 125 125 + 127: 90(ivec4) SpecConstantOp 198 91 126 128: 6(int) SpecConstantOp 81 87 0 129: TypeVector 6(int) 2 130: 129(ivec2) SpecConstantOp 79 87 87 1(GLSL.std.450) 0 131: TypeVector 6(int) 3 132: 131(ivec3) SpecConstantOp 79 87 87 2 1(GLSL.std.450) 0 - 133: 85(ivec4) SpecConstantOp 79 87 87 1(GLSL.std.450) 2 0 3 + 133: 86(ivec4) SpecConstantOp 79 87 87 1(GLSL.std.450) 2 0 3 4(main): 2 Function None 3 5: Label Return diff --git a/Test/spv.specConstantComposite.vert b/Test/spv.specConstantComposite.vert index 4450ddd6..01103302 100644 --- a/Test/spv.specConstantComposite.vert +++ b/Test/spv.specConstantComposite.vert @@ -42,6 +42,11 @@ const vec4 spec_vec4_all_spec = vec4(spec_float, spec_float, spec_float, spec_float); const vec4 spec_vec4_partial_spec = vec4(spec_float, spec_float, 300.14, 300.14); +const vec4 spec_vec4_from_one_scalar = vec4(spec_float); + +// Matrix constructor +const mat2x3 spec_mat2x3 = mat2x3(spec_float, spec_float, spec_float, 1.1, 2.2, 3.3); +const mat2x3 spec_mat2x3_from_one_scalar = mat2x3(spec_float); // Struct nesting constructor const nesting_struct spec_nesting_struct_all_spec = {