diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index bf26cdcf..02609d01 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1775,7 +1775,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang // return true if a single operand to ? : is okay for OpSelect const auto operandOkay = [](glslang::TIntermTyped* node) { - return node->getAsSymbolNode() || node->getAsConstantUnion(); + return node->getAsSymbolNode() || node->getType().getQualifier().isConstant(); }; return operandOkay(node->getTrueBlock() ->getAsTyped()) && @@ -1799,6 +1799,10 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang // Try for OpSelect if (selectPolicy()) { + SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); + if (node->getType().getQualifier().isSpecConstant()) + spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); + handleAsOpSelect(); return false; } diff --git a/Test/baseResults/spv.specConstantOperations.vert.out b/Test/baseResults/spv.specConstantOperations.vert.out index d6da726e..597820b9 100644 --- a/Test/baseResults/spv.specConstantOperations.vert.out +++ b/Test/baseResults/spv.specConstantOperations.vert.out @@ -3,7 +3,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre // Module Version 10000 // Generated by (magic number): 80001 -// Id's are bound by 135 +// Id's are bound by 160 Capability Shader Capability Float64 @@ -20,11 +20,18 @@ Warning, version 450 is not yet complete; most version-specific features are pre Name 42 "sp_uint" Name 43 "sp_sint" Name 45 "sp_double" + Name 135 "a" + Name 136 "b" + Name 137 "c" + Name 142 "ternayArray1" Decorate 19(sp_int) SpecId 201 Decorate 40(sp_float) SpecId 200 Decorate 42(sp_uint) SpecId 202 Decorate 43(sp_sint) SpecId 203 Decorate 45(sp_double) SpecId 204 + Decorate 135(a) SpecId 210 + Decorate 136(b) SpecId 211 + Decorate 137(c) SpecId 212 2: TypeVoid 3: TypeFunction 2 6: TypeInt 32 1 @@ -137,6 +144,31 @@ Warning, version 450 is not yet complete; most version-specific features are pre 132: TypeVector 6(int) 3 133: 132(ivec3) SpecConstantOp 79 91 91 2 1(GLSL.std.450) 0 134: 90(ivec4) SpecConstantOp 79 91 91 1(GLSL.std.450) 2 0 3 + 135(a): 6(int) SpecConstant 4 + 136(b): 6(int) SpecConstant 6 + 137(c): 22(bool) SpecConstantTrue + 138: 22(bool) SpecConstantOp 173 135(a) 136(b) + 139: 6(int) SpecConstantOp 169 138 135(a) 136(b) + 140: TypeArray 6(int) 139 + 141: TypePointer Private 140 +142(ternayArray1): 141(ptr) Variable Private + 143: 6(int) Constant 13 + 144: 6(int) Constant 17 + 145: 6(int) SpecConstantOp 169 137(c) 143 144 + 146: 6(int) SpecConstantOp 169 137(c) 135(a) 144 + 147: 22(bool) ConstantTrue + 148: 6(int) SpecConstantOp 169 147 135(a) 144 + 149: 22(bool) SpecConstantOp 173 135(a) 136(b) + 150: 6(int) SpecConstantOp 128 143 135(a) + 151: 6(int) SpecConstantOp 132 144 136(b) + 152: 6(int) SpecConstantOp 169 149 150 151 + 153: 22(bool) SpecConstantOp 168 137(c) + 154: TypeVector 39(float) 2 + 155: 39(float) Constant 1065353216 + 156: 154(fvec2) ConstantComposite 155 155 + 157: 39(float) Constant 1073741824 + 158: 154(fvec2) ConstantComposite 157 157 + 159: 154(fvec2) SpecConstantOp 169 153 156 158 4(main): 2 Function None 3 5: Label Return diff --git a/Test/spv.specConstantOperations.vert b/Test/spv.specConstantOperations.vert index f67561c3..93be12c5 100644 --- a/Test/spv.specConstantOperations.vert +++ b/Test/spv.specConstantOperations.vert @@ -110,5 +110,15 @@ int non_const_array_size_from_spec_const() { return array[sp_int + 1]; } -void main() {} +// ternary +layout(constant_id = 210) const int a = 4; +layout(constant_id = 211) const int b = 6; +layout(constant_id = 212) const bool c = true; +int ternayArray1[a > b ? a : b]; +const int t1 = c ? 13 : 17; +const int t2 = c ? a : 17; +const int t3 = true ? a : 17; +const int t4 = a > b ? 13 + a : 17 * b; +const vec2 v2 = !c ? vec2(1.0) : vec2(2.0); +void main() {} diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index af3e8119..28542355 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -155,14 +155,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn return folded; } - // If either is a specialization constant, while the other is - // a constant (or specialization constant), the result is still - // a specialization constant, if the operation is an allowed - // specialization-constant operation. - if (( left->getType().getQualifier().isSpecConstant() && right->getType().getQualifier().isConstant()) || - (right->getType().getQualifier().isSpecConstant() && left->getType().getQualifier().isConstant())) - if (isSpecializationOperation(*node)) - node->getWritableType().getQualifier().makeSpecConstant(); + // If can propagate spec-constantness and if the operation is an allowed + // specialization-constant operation, make a spec-constant. + if (specConstantPropagates(*left, *right) && isSpecializationOperation(*node)) + node->getWritableType().getQualifier().makeSpecConstant(); return node; } @@ -1277,6 +1273,9 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, // a true path, and a false path. The two paths are specified // as separate parameters. // +// Specialization constant operations include +// - The ternary operator ( ? : ) +// // Returns the selection node created, or nullptr if one could not be. // TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc) @@ -1320,10 +1319,16 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Make a selection node. // TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->getQualifier().makeTemporary(); node->setLoc(loc); node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); + if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) || + (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() && + falseBlock->getQualifier().isConstant())) + node->getQualifier().makeSpecConstant(); + else + node->getQualifier().makeTemporary(); + return node; } @@ -2645,4 +2650,13 @@ void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable) *pragmaTable = pTable; } +// If either node is a specialization constant, while the other is +// a constant (or specialization constant), the result is still +// a specialization constant. +bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2) +{ + return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) || + (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant()); +} + } // end namespace glslang diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 29efb54c..75bd679e 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -440,6 +440,7 @@ protected: bool promoteAggregate(TIntermAggregate&); void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); const EShLanguage language; // stage, known at construction time EShSource source; // source language, known a bit later