SPV: Implement specialization constants for ?:.

This commit is contained in:
John Kessenich 2017-01-28 19:29:42 -07:00
parent 433e9ff896
commit 8e6c6cef6a
5 changed files with 73 additions and 12 deletions

View File

@ -1775,7 +1775,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// return true if a single operand to ? : is okay for OpSelect // return true if a single operand to ? : is okay for OpSelect
const auto operandOkay = [](glslang::TIntermTyped* node) { const auto operandOkay = [](glslang::TIntermTyped* node) {
return node->getAsSymbolNode() || node->getAsConstantUnion(); return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
}; };
return operandOkay(node->getTrueBlock() ->getAsTyped()) && return operandOkay(node->getTrueBlock() ->getAsTyped()) &&
@ -1799,6 +1799,10 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// Try for OpSelect // Try for OpSelect
if (selectPolicy()) { if (selectPolicy()) {
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
handleAsOpSelect(); handleAsOpSelect();
return false; return false;
} }

View File

@ -3,7 +3,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 135 // Id's are bound by 160
Capability Shader Capability Shader
Capability Float64 Capability Float64
@ -20,11 +20,18 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Name 42 "sp_uint" Name 42 "sp_uint"
Name 43 "sp_sint" Name 43 "sp_sint"
Name 45 "sp_double" Name 45 "sp_double"
Name 135 "a"
Name 136 "b"
Name 137 "c"
Name 142 "ternayArray1"
Decorate 19(sp_int) SpecId 201 Decorate 19(sp_int) SpecId 201
Decorate 40(sp_float) SpecId 200 Decorate 40(sp_float) SpecId 200
Decorate 42(sp_uint) SpecId 202 Decorate 42(sp_uint) SpecId 202
Decorate 43(sp_sint) SpecId 203 Decorate 43(sp_sint) SpecId 203
Decorate 45(sp_double) SpecId 204 Decorate 45(sp_double) SpecId 204
Decorate 135(a) SpecId 210
Decorate 136(b) SpecId 211
Decorate 137(c) SpecId 212
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeInt 32 1 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 132: TypeVector 6(int) 3
133: 132(ivec3) SpecConstantOp 79 91 91 2 1(GLSL.std.450) 0 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 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 4(main): 2 Function None 3
5: Label 5: Label
Return Return

View File

@ -110,5 +110,15 @@ int non_const_array_size_from_spec_const() {
return array[sp_int + 1]; 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() {}

View File

@ -155,14 +155,10 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
return folded; return folded;
} }
// If either is a specialization constant, while the other is // If can propagate spec-constantness and if the operation is an allowed
// a constant (or specialization constant), the result is still // specialization-constant operation, make a spec-constant.
// a specialization constant, if the operation is an allowed if (specConstantPropagates(*left, *right) && isSpecializationOperation(*node))
// specialization-constant operation. node->getWritableType().getQualifier().makeSpecConstant();
if (( left->getType().getQualifier().isSpecConstant() && right->getType().getQualifier().isConstant()) ||
(right->getType().getQualifier().isSpecConstant() && left->getType().getQualifier().isConstant()))
if (isSpecializationOperation(*node))
node->getWritableType().getQualifier().makeSpecConstant();
return node; 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 // a true path, and a false path. The two paths are specified
// as separate parameters. // as separate parameters.
// //
// Specialization constant operations include
// - The ternary operator ( ? : )
//
// Returns the selection node created, or nullptr if one could not be. // Returns the selection node created, or nullptr if one could not be.
// //
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc) 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. // Make a selection node.
// //
TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
node->getQualifier().makeTemporary();
node->setLoc(loc); node->setLoc(loc);
node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); 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; return node;
} }
@ -2645,4 +2650,13 @@ void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
*pragmaTable = 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 } // end namespace glslang

View File

@ -440,6 +440,7 @@ protected:
bool promoteAggregate(TIntermAggregate&); bool promoteAggregate(TIntermAggregate&);
void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
const EShLanguage language; // stage, known at construction time const EShLanguage language; // stage, known at construction time
EShSource source; // source language, known a bit later EShSource source; // source language, known a bit later