Commit 07939886 by John Kessenich Committed by GitHub

Merge pull request #707 from KhronosGroup/emit-opSelect

SPV: Emit op select
parents f8d0d8c2 8e6c6cef
......@@ -1748,42 +1748,98 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
}
}
// This path handles both if-then-else and ?:
// The if-then-else has a node type of void, while
// ?: has either a void or a non-void node type
//
// Leaving the result, when not void:
// GLSL only has r-values as the result of a :?, but
// if we have an l-value, that can be more efficient if it will
// become the base of a complex r-value expression, because the
// next layer copies r-values into memory to use the access-chain mechanism
bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
{
// This path handles both if-then-else and ?:
// The if-then-else has a node type of void, while
// ?: has a non-void node type
spv::Id result = 0;
if (node->getBasicType() != glslang::EbtVoid) {
// don't handle this as just on-the-fly temporaries, because there will be two names
// and better to leave SSA to later passes
result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
// See if it simple and safe to generate OpSelect instead of using control flow.
// Crucially, side effects must be avoided, and there are performance trade-offs.
// Return true if good idea (and safe) for OpSelect, false otherwise.
const auto selectPolicy = [&]() -> bool {
if (node->getBasicType() == glslang::EbtVoid)
return false;
if (node->getTrueBlock() == nullptr ||
node->getFalseBlock() == nullptr)
return false;
assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
node->getType() == node->getFalseBlock()->getAsTyped()->getType());
// return true if a single operand to ? : is okay for OpSelect
const auto operandOkay = [](glslang::TIntermTyped* node) {
return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
};
return operandOkay(node->getTrueBlock() ->getAsTyped()) &&
operandOkay(node->getFalseBlock()->getAsTyped());
};
// Emit OpSelect for this selection.
const auto handleAsOpSelect = [&]() {
node->getCondition()->traverse(this);
spv::Id condition = accessChainLoad(node->getCondition()->getType());
node->getTrueBlock()->traverse(this);
spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
spv::Id select = builder.createTriOp(spv::OpSelect, convertGlslangToSpvType(node->getType()), condition, trueValue, falseValue);
builder.clearAccessChain();
builder.setAccessChainRValue(select);
};
// 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;
}
// Instead, emit control flow...
// Don't handle results as temporaries, because there will be two names
// and better to leave SSA to later passes.
spv::Id result = (node->getBasicType() == glslang::EbtVoid)
? spv::NoResult
: builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
// emit the condition before doing anything with selection
node->getCondition()->traverse(this);
// make an "if" based on the value created by the condition
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), builder);
if (node->getTrueBlock()) {
// emit the "then" statement
// emit the "then" statement
if (node->getTrueBlock() != nullptr) {
node->getTrueBlock()->traverse(this);
if (result)
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
}
if (node->getFalseBlock()) {
if (node->getFalseBlock() != nullptr) {
ifBuilder.makeBeginElse();
// emit the "else" statement
node->getFalseBlock()->traverse(this);
if (result)
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
}
// finish off the control flow
ifBuilder.makeEndIf();
if (result) {
if (result != spv::NoResult) {
// GLSL only has r-values as the result of a :?, but
// if we have an l-value, that can be more efficient if it will
// become the base of a complex r-value expression, because the
......
......@@ -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 49
// Id's are bound by 44
Capability Shader
1: ExtInstImport "GLSL.std.450"
......@@ -19,18 +19,18 @@ Warning, version 450 is not yet complete; most version-specific features are pre
MemberName 22(gl_PerVertex) 2 "gl_ClipDistance"
MemberName 22(gl_PerVertex) 3 "gl_CullDistance"
Name 24 ""
Name 29 "ubname"
MemberName 29(ubname) 0 "b"
Name 31 "ubinst"
Name 32 "param"
Name 27 "ubname"
MemberName 27(ubname) 0 "b"
Name 29 "ubinst"
Name 30 "param"
MemberDecorate 22(gl_PerVertex) 0 BuiltIn Position
MemberDecorate 22(gl_PerVertex) 1 BuiltIn PointSize
MemberDecorate 22(gl_PerVertex) 2 BuiltIn ClipDistance
MemberDecorate 22(gl_PerVertex) 3 BuiltIn CullDistance
Decorate 22(gl_PerVertex) Block
MemberDecorate 29(ubname) 0 Offset 0
Decorate 29(ubname) Block
Decorate 31(ubinst) DescriptorSet 0
MemberDecorate 27(ubname) 0 Offset 0
Decorate 27(ubname) Block
Decorate 29(ubinst) DescriptorSet 0
2: TypeVoid
3: TypeFunction 2
6: TypeBool
......@@ -47,38 +47,27 @@ Warning, version 450 is not yet complete; most version-specific features are pre
24: 23(ptr) Variable Output
25: TypeInt 32 1
26: 25(int) Constant 0
27: TypePointer Function 18(fvec4)
29(ubname): TypeStruct 19(int)
30: TypePointer Uniform 29(ubname)
31(ubinst): 30(ptr) Variable Uniform
33: TypePointer Uniform 19(int)
36: 19(int) Constant 0
41: 17(float) Constant 0
42: 18(fvec4) ConstantComposite 41 41 41 41
44: 17(float) Constant 1065353216
45: 18(fvec4) ConstantComposite 44 44 44 44
47: TypePointer Output 18(fvec4)
27(ubname): TypeStruct 19(int)
28: TypePointer Uniform 27(ubname)
29(ubinst): 28(ptr) Variable Uniform
31: TypePointer Uniform 19(int)
34: 19(int) Constant 0
37: 17(float) Constant 0
38: 18(fvec4) ConstantComposite 37 37 37 37
39: 17(float) Constant 1065353216
40: 18(fvec4) ConstantComposite 39 39 39 39
42: TypePointer Output 18(fvec4)
4(main): 2 Function None 3
5: Label
28: 27(ptr) Variable Function
32(param): 7(ptr) Variable Function
34: 33(ptr) AccessChain 31(ubinst) 26
35: 19(int) Load 34
37: 6(bool) INotEqual 35 36
Store 32(param) 37
38: 6(bool) FunctionCall 10(foo(b1;) 32(param)
SelectionMerge 40 None
BranchConditional 38 39 43
39: Label
Store 28 42
Branch 40
43: Label
Store 28 45
Branch 40
40: Label
46: 18(fvec4) Load 28
48: 47(ptr) AccessChain 24 26
Store 48 46
30(param): 7(ptr) Variable Function
32: 31(ptr) AccessChain 29(ubinst) 26
33: 19(int) Load 32
35: 6(bool) INotEqual 33 34
Store 30(param) 35
36: 6(bool) FunctionCall 10(foo(b1;) 30(param)
41: 18(fvec4) Select 36 38 40
43: 42(ptr) AccessChain 24 26
Store 43 41
Return
FunctionEnd
10(foo(b1;): 6(bool) Function None 8
......
spv.deepRvalue.frag
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 155
// Id's are bound by 150
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 149
EntryPoint Fragment 4 "main" 144
ExecutionMode 4 OriginUpperLeft
Source GLSL 330
Name 4 "main"
......@@ -21,12 +21,12 @@ spv.deepRvalue.frag
Name 106 "h"
Name 107 "i"
Name 111 "samp2D"
Name 134 "str"
MemberName 134(str) 0 "a"
MemberName 134(str) 1 "b"
MemberName 134(str) 2 "c"
Name 136 "t"
Name 149 "gl_FragColor"
Name 129 "str"
MemberName 129(str) 0 "a"
MemberName 129(str) 1 "b"
MemberName 129(str) 2 "c"
Name 131 "t"
Name 144 "gl_FragColor"
Decorate 111(samp2D) DescriptorSet 0
2: TypeVoid
3: TypeFunction 2
......@@ -75,22 +75,21 @@ spv.deepRvalue.frag
113: TypeVector 6(float) 2
114: 6(float) Constant 1056964608
115: 113(fvec2) ConstantComposite 114 114
118: TypePointer Function 7(fvec4)
121: 6(float) Constant 1036831949
122: TypeBool
133: TypeArray 113(fvec2) 84
134(str): TypeStruct 81(int) 133 122(bool)
135: TypePointer Function 134(str)
137: 113(fvec2) ConstantComposite 10 11
138: 6(float) Constant 1082130432
139: 113(fvec2) ConstantComposite 138 12
140: 6(float) Constant 1086324736
141: 113(fvec2) ConstantComposite 140 13
142: 133 ConstantComposite 137 139 141
143: 122(bool) ConstantTrue
144: 134(str) ConstantComposite 82 142 143
148: TypePointer Output 7(fvec4)
149(gl_FragColor): 148(ptr) Variable Output
119: 6(float) Constant 1036831949
120: TypeBool
128: TypeArray 113(fvec2) 84
129(str): TypeStruct 81(int) 128 120(bool)
130: TypePointer Function 129(str)
132: 113(fvec2) ConstantComposite 10 11
133: 6(float) Constant 1082130432
134: 113(fvec2) ConstantComposite 133 12
135: 6(float) Constant 1086324736
136: 113(fvec2) ConstantComposite 135 13
137: 128 ConstantComposite 132 134 136
138: 120(bool) ConstantTrue
139: 129(str) ConstantComposite 82 137 138
143: TypePointer Output 7(fvec4)
144(gl_FragColor): 143(ptr) Variable Output
4(main): 2 Function None 3
5: Label
35(m): 34(ptr) Variable Function
......@@ -99,8 +98,7 @@ spv.deepRvalue.frag
87(g): 79(ptr) Variable Function
106(h): 79(ptr) Variable Function
107(i): 79(ptr) Variable Function
119: 118(ptr) Variable Function
136(t): 135(ptr) Variable Function
131(t): 130(ptr) Variable Function
Store 9(v1) 14
Store 15(v2) 20
Store 21(v3) 26
......@@ -172,34 +170,25 @@ spv.deepRvalue.frag
116: 7(fvec4) ImageSampleImplicitLod 112 115
117: 6(float) CompositeExtract 116 1
Store 107(i) 117
120: 6(float) Load 107(i)
123: 122(bool) FOrdGreaterThan 120 121
SelectionMerge 125 None
BranchConditional 123 124 127
124: Label
126: 7(fvec4) Load 9(v1)
Store 119 126
Branch 125
127: Label
128: 7(fvec4) Load 15(v2)
Store 119 128
Branch 125
125: Label
129: 79(ptr) AccessChain 119 84
130: 6(float) Load 129
131: 6(float) Load 107(i)
132: 6(float) FAdd 131 130
Store 107(i) 132
Store 136(t) 144
145: 6(float) CompositeExtract 144 1 2 1
146: 6(float) Load 107(i)
147: 6(float) FAdd 146 145
Store 107(i) 147
150: 6(float) Load 80(f)
151: 6(float) Load 87(g)
152: 6(float) Load 106(h)
153: 6(float) Load 107(i)
154: 7(fvec4) CompositeConstruct 150 151 152 153
Store 149(gl_FragColor) 154
118: 6(float) Load 107(i)
121: 120(bool) FOrdGreaterThan 118 119
122: 7(fvec4) Load 9(v1)
123: 7(fvec4) Load 15(v2)
124: 7(fvec4) Select 121 122 123
125: 6(float) CompositeExtract 124 3
126: 6(float) Load 107(i)
127: 6(float) FAdd 126 125
Store 107(i) 127
Store 131(t) 139
140: 6(float) CompositeExtract 139 1 2 1
141: 6(float) Load 107(i)
142: 6(float) FAdd 141 140
Store 107(i) 142
145: 6(float) Load 80(f)
146: 6(float) Load 87(g)
147: 6(float) Load 106(h)
148: 6(float) Load 107(i)
149: 7(fvec4) CompositeConstruct 145 146 147 148
Store 144(gl_FragColor) 149
Return
FunctionEnd
......@@ -3,38 +3,37 @@ 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 35
// Id's are bound by 31
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Vertex 4 "main" 18 31
EntryPoint Vertex 4 "main" 17 27
Source GLSL 450
Name 4 "main"
Name 8 "i"
Name 18 "flag"
Name 31 "r"
Decorate 18(flag) RelaxedPrecision
Decorate 18(flag) Location 0
Decorate 19 RelaxedPrecision
Decorate 31(r) Location 0
Name 17 "flag"
Name 27 "r"
Decorate 17(flag) RelaxedPrecision
Decorate 17(flag) Location 0
Decorate 18 RelaxedPrecision
Decorate 27(r) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 1
7: TypePointer Function 6(int)
9: 6(int) Constant 0
17: TypePointer Input 6(int)
18(flag): 17(ptr) Variable Input
20: 6(int) Constant 1
21: TypeBool
25: 6(int) Constant 10
27: 6(int) Constant 15
30: TypePointer Output 6(int)
31(r): 30(ptr) Variable Output
16: TypePointer Input 6(int)
17(flag): 16(ptr) Variable Input
19: 6(int) Constant 1
20: TypeBool
22: 6(int) Constant 10
23: 6(int) Constant 15
26: TypePointer Output 6(int)
27(r): 26(ptr) Variable Output
4(main): 2 Function None 3
5: Label
8(i): 7(ptr) Variable Function
16: 7(ptr) Variable Function
Store 8(i) 9
Branch 10
10: Label
......@@ -42,29 +41,20 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Branch 14
14: Label
15: 6(int) Load 8(i)
19: 6(int) Load 18(flag)
22: 21(bool) IEqual 19 20
SelectionMerge 24 None
BranchConditional 22 23 26
23: Label
Store 16 25
Branch 24
26: Label
Store 16 27
Branch 24
24: Label
28: 6(int) Load 16
29: 21(bool) SLessThan 15 28
BranchConditional 29 11 12
11: Label
32: 6(int) Load 8(i)
Store 31(r) 32
Branch 13
13: Label
33: 6(int) Load 8(i)
34: 6(int) IAdd 33 20
Store 8(i) 34
Branch 10
18: 6(int) Load 17(flag)
21: 20(bool) IEqual 18 19
24: 6(int) Select 21 22 23
25: 20(bool) SLessThan 15 24
BranchConditional 25 11 12
11: Label
28: 6(int) Load 8(i)
Store 27(r) 28
Branch 13
13: Label
29: 6(int) Load 8(i)
30: 6(int) IAdd 29 19
Store 8(i) 30
Branch 10
12: Label
Return
FunctionEnd
......@@ -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 378
// Id's are bound by 374
Capability Shader
Capability SampledRect
......@@ -16,7 +16,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Capability StorageImageWriteWithoutFormat
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 132 142 152 248 362 377
EntryPoint Fragment 4 "main" 132 142 152 248 362 373
ExecutionMode 4 OriginUpperLeft
Source GLSL 450
Name 4 "main"
......@@ -42,7 +42,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Name 248 "value"
Name 357 "wo2D"
Name 362 "fragData"
Name 377 "ic4D"
Name 373 "ic4D"
Decorate 15(i1D) DescriptorSet 0
Decorate 15(i1D) Binding 0
Decorate 27(i2D) DescriptorSet 0
......@@ -76,7 +76,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
Decorate 357(wo2D) DescriptorSet 0
Decorate 357(wo2D) Binding 1
Decorate 357(wo2D) NonReadable
Decorate 377(ic4D) Flat
Decorate 373(ic4D) Flat
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 1
......@@ -163,16 +163,15 @@ Warning, version 450 is not yet complete; most version-specific features are pre
357(wo2D): 356(ptr) Variable UniformConstant
361: TypePointer Output 125(fvec4)
362(fragData): 361(ptr) Variable Output
368: TypeBool
375: TypeVector 6(int) 4
376: TypePointer Input 375(ivec4)
377(ic4D): 376(ptr) Variable Input
367: TypeBool
371: TypeVector 6(int) 4
372: TypePointer Input 371(ivec4)
373(ic4D): 372(ptr) Variable Input
4(main): 2 Function None 3
5: Label
9(iv): 8(ptr) Variable Function
127(v): 126(ptr) Variable Function
229(ui): 228(ptr) Variable Function
363: 126(ptr) Variable Function
Store 9(iv) 11
16: 13 Load 15(i1D)
17: 6(int) ImageQuerySize 16
......@@ -498,22 +497,13 @@ Warning, version 450 is not yet complete; most version-specific features are pre
359: 29(ivec2) Load 142(ic2D)
360: 125(fvec4) Load 127(v)
ImageWrite 358 359 360
364: 18(int) Load 229(ui)
365: 20(ptr) AccessChain 9(iv) 237
366: 6(int) Load 365
367: 18(int) Bitcast 366
369: 368(bool) INotEqual 364 367
SelectionMerge 371 None
BranchConditional 369 370 373
370: Label
372: 125(fvec4) Load 127(v)
Store 363 372
Branch 371
373: Label
Store 363 129
Branch 371
371: Label
374: 125(fvec4) Load 363
Store 362(fragData) 374
363: 18(int) Load 229(ui)
364: 20(ptr) AccessChain 9(iv) 237
365: 6(int) Load 364
366: 18(int) Bitcast 365
368: 367(bool) INotEqual 363 366
369: 125(fvec4) Load 127(v)
370: 125(fvec4) Select 368 369 129
Store 362(fragData) 370
Return
FunctionEnd
......@@ -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
......
......@@ -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() {}
......@@ -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
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment