SPV 1.4: Use OpSelect for trivial typed non-scalar/vector expressions.
This commit is contained in:
parent
cfea59d357
commit
0c1e71a123
@ -2615,6 +2615,19 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||||||
// next layer copies r-values into memory to use the access-chain mechanism
|
// next layer copies r-values into memory to use the access-chain mechanism
|
||||||
bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
|
bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
|
||||||
{
|
{
|
||||||
|
// see if OpSelect can handle it
|
||||||
|
const auto isOpSelectable = [&]() {
|
||||||
|
if (node->getBasicType() == glslang::EbtVoid)
|
||||||
|
return false;
|
||||||
|
// OpSelect can do all other types starting with SPV 1.4
|
||||||
|
if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) {
|
||||||
|
// pre-1.4, only scalars and vectors can be handled
|
||||||
|
if ((!node->getType().isScalar() && !node->getType().isVector()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// See if it simple and safe, or required, to execute both sides.
|
// See if it simple and safe, or required, to execute both sides.
|
||||||
// Crucially, side effects must be either semantically required or avoided,
|
// Crucially, side effects must be either semantically required or avoided,
|
||||||
// and there are performance trade-offs.
|
// and there are performance trade-offs.
|
||||||
@ -2633,9 +2646,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||||||
|
|
||||||
// if not required to execute both, decide based on performance/practicality...
|
// if not required to execute both, decide based on performance/practicality...
|
||||||
|
|
||||||
// see if OpSelect can handle it
|
if (!isOpSelectable())
|
||||||
if ((!node->getType().isScalar() && !node->getType().isVector()) ||
|
|
||||||
node->getBasicType() == glslang::EbtVoid)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
|
assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
|
||||||
@ -2672,14 +2683,16 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||||||
// emit code to select between trueValue and falseValue
|
// emit code to select between trueValue and falseValue
|
||||||
|
|
||||||
// see if OpSelect can handle it
|
// see if OpSelect can handle it
|
||||||
if (node->getType().isScalar() || node->getType().isVector()) {
|
if (isOpSelectable()) {
|
||||||
// Emit OpSelect for this selection.
|
// Emit OpSelect for this selection.
|
||||||
|
|
||||||
// smear condition to vector, if necessary (AST is always scalar)
|
// smear condition to vector, if necessary (AST is always scalar)
|
||||||
if (builder.isVector(trueValue))
|
// Before 1.4, smear like for mix(), starting with 1.4, keep it scalar
|
||||||
|
if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) {
|
||||||
condition = builder.smearScalar(spv::NoPrecision, condition,
|
condition = builder.smearScalar(spv::NoPrecision, condition,
|
||||||
builder.makeVectorType(builder.makeBoolType(),
|
builder.makeVectorType(builder.makeBoolType(),
|
||||||
builder.getNumComponents(trueValue)));
|
builder.getNumComponents(trueValue)));
|
||||||
|
}
|
||||||
|
|
||||||
// OpSelect
|
// OpSelect
|
||||||
result = builder.createTriOp(spv::OpSelect,
|
result = builder.createTriOp(spv::OpSelect,
|
||||||
|
153
Test/baseResults/spv.1.4.OpSelect.frag.out
Executable file
153
Test/baseResults/spv.1.4.OpSelect.frag.out
Executable file
@ -0,0 +1,153 @@
|
|||||||
|
spv.1.4.OpSelect.frag
|
||||||
|
Validation failed
|
||||||
|
// Module Version 10400
|
||||||
|
// Generated by (magic number): 80007
|
||||||
|
// Id's are bound by 98
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Fragment 4 "main" 17 20 82 84
|
||||||
|
ExecutionMode 4 OriginUpperLeft
|
||||||
|
Source GLSL 450
|
||||||
|
Name 4 "main"
|
||||||
|
Name 6 "fun1("
|
||||||
|
Name 8 "fun2("
|
||||||
|
Name 12 "f1"
|
||||||
|
Name 14 "f2"
|
||||||
|
Name 17 "outv"
|
||||||
|
Name 20 "cond"
|
||||||
|
Name 30 "iv1"
|
||||||
|
Name 34 "iv2"
|
||||||
|
Name 53 "m1"
|
||||||
|
Name 59 "m2"
|
||||||
|
Name 75 "S1"
|
||||||
|
MemberName 75(S1) 0 "a"
|
||||||
|
MemberName 75(S1) 1 "b"
|
||||||
|
Name 77 "fv"
|
||||||
|
Name 82 "in1"
|
||||||
|
Name 84 "in2"
|
||||||
|
Decorate 17(outv) Location 0
|
||||||
|
Decorate 20(cond) Flat
|
||||||
|
Decorate 20(cond) Location 4
|
||||||
|
Decorate 82(in1) Flat
|
||||||
|
Decorate 82(in1) Location 0
|
||||||
|
Decorate 84(in2) Flat
|
||||||
|
Decorate 84(in2) Location 2
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
10: TypeFloat 32
|
||||||
|
11: TypePointer Function 10(float)
|
||||||
|
13: 10(float) Constant 1065353216
|
||||||
|
15: 10(float) Constant 1073741824
|
||||||
|
16: TypePointer Output 10(float)
|
||||||
|
17(outv): 16(ptr) Variable Output
|
||||||
|
18: TypeInt 32 1
|
||||||
|
19: TypePointer Input 18(int)
|
||||||
|
20(cond): 19(ptr) Variable Input
|
||||||
|
22: 18(int) Constant 8
|
||||||
|
23: TypeBool
|
||||||
|
28: TypeVector 18(int) 4
|
||||||
|
29: TypePointer Function 28(ivec4)
|
||||||
|
39: 18(int) Constant 0
|
||||||
|
44: TypeInt 32 0
|
||||||
|
45: 44(int) Constant 2
|
||||||
|
50: TypeVector 10(float) 3
|
||||||
|
51: TypeMatrix 50(fvec3) 3
|
||||||
|
52: TypePointer Function 51
|
||||||
|
54: 10(float) Constant 0
|
||||||
|
55: 50(fvec3) ConstantComposite 13 54 54
|
||||||
|
56: 50(fvec3) ConstantComposite 54 13 54
|
||||||
|
57: 50(fvec3) ConstantComposite 54 54 13
|
||||||
|
58: 51 ConstantComposite 55 56 57
|
||||||
|
60: 50(fvec3) ConstantComposite 15 54 54
|
||||||
|
61: 50(fvec3) ConstantComposite 54 15 54
|
||||||
|
62: 50(fvec3) ConstantComposite 54 54 15
|
||||||
|
63: 51 ConstantComposite 60 61 62
|
||||||
|
65: 18(int) Constant 20
|
||||||
|
70: 18(int) Constant 2
|
||||||
|
71: 44(int) Constant 1
|
||||||
|
75(S1): TypeStruct 10(float) 18(int)
|
||||||
|
76: TypePointer Function 75(S1)
|
||||||
|
79: 18(int) Constant 5
|
||||||
|
81: TypePointer Input 75(S1)
|
||||||
|
82(in1): 81(ptr) Variable Input
|
||||||
|
84(in2): 81(ptr) Variable Input
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
12(f1): 11(ptr) Variable Function
|
||||||
|
14(f2): 11(ptr) Variable Function
|
||||||
|
30(iv1): 29(ptr) Variable Function
|
||||||
|
34(iv2): 29(ptr) Variable Function
|
||||||
|
53(m1): 52(ptr) Variable Function
|
||||||
|
59(m2): 52(ptr) Variable Function
|
||||||
|
77(fv): 76(ptr) Variable Function
|
||||||
|
Store 12(f1) 13
|
||||||
|
Store 14(f2) 15
|
||||||
|
21: 18(int) Load 20(cond)
|
||||||
|
24: 23(bool) SLessThan 21 22
|
||||||
|
25: 10(float) Load 12(f1)
|
||||||
|
26: 10(float) Load 14(f2)
|
||||||
|
27: 10(float) Select 24 25 26
|
||||||
|
Store 17(outv) 27
|
||||||
|
31: 10(float) Load 12(f1)
|
||||||
|
32: 18(int) ConvertFToS 31
|
||||||
|
33: 28(ivec4) CompositeConstruct 32 32 32 32
|
||||||
|
Store 30(iv1) 33
|
||||||
|
35: 10(float) Load 14(f2)
|
||||||
|
36: 18(int) ConvertFToS 35
|
||||||
|
37: 28(ivec4) CompositeConstruct 36 36 36 36
|
||||||
|
Store 34(iv2) 37
|
||||||
|
38: 18(int) Load 20(cond)
|
||||||
|
40: 23(bool) SGreaterThan 38 39
|
||||||
|
41: 28(ivec4) Load 30(iv1)
|
||||||
|
42: 28(ivec4) Load 34(iv2)
|
||||||
|
43: 28(ivec4) Select 40 41 42
|
||||||
|
46: 18(int) CompositeExtract 43 2
|
||||||
|
47: 10(float) ConvertSToF 46
|
||||||
|
48: 10(float) Load 17(outv)
|
||||||
|
49: 10(float) FMul 48 47
|
||||||
|
Store 17(outv) 49
|
||||||
|
Store 53(m1) 58
|
||||||
|
Store 59(m2) 63
|
||||||
|
64: 18(int) Load 20(cond)
|
||||||
|
66: 23(bool) SLessThan 64 65
|
||||||
|
67: 51 Load 53(m1)
|
||||||
|
68: 51 Load 59(m2)
|
||||||
|
69: 51 Select 66 67 68
|
||||||
|
72: 10(float) CompositeExtract 69 2 1
|
||||||
|
73: 10(float) Load 17(outv)
|
||||||
|
74: 10(float) FMul 73 72
|
||||||
|
Store 17(outv) 74
|
||||||
|
78: 18(int) Load 20(cond)
|
||||||
|
80: 23(bool) SGreaterThan 78 79
|
||||||
|
83: 75(S1) Load 82(in1)
|
||||||
|
85: 75(S1) Load 84(in2)
|
||||||
|
86: 75(S1) Select 80 83 85
|
||||||
|
Store 77(fv) 86
|
||||||
|
87: 11(ptr) AccessChain 77(fv) 39
|
||||||
|
88: 10(float) Load 87
|
||||||
|
89: 10(float) Load 17(outv)
|
||||||
|
90: 10(float) FMul 89 88
|
||||||
|
Store 17(outv) 90
|
||||||
|
91: 18(int) Load 20(cond)
|
||||||
|
92: 23(bool) SGreaterThan 91 39
|
||||||
|
SelectionMerge 94 None
|
||||||
|
BranchConditional 92 93 96
|
||||||
|
93: Label
|
||||||
|
95: 2 FunctionCall 6(fun1()
|
||||||
|
Branch 94
|
||||||
|
96: Label
|
||||||
|
97: 2 FunctionCall 8(fun2()
|
||||||
|
Branch 94
|
||||||
|
94: Label
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
6(fun1(): 2 Function None 3
|
||||||
|
7: Label
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
8(fun2(): 2 Function None 3
|
||||||
|
9: Label
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
37
Test/spv.1.4.OpSelect.frag
Executable file
37
Test/spv.1.4.OpSelect.frag
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
struct S1 {
|
||||||
|
float a;
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) flat in S1 in1;
|
||||||
|
layout(location = 2) flat in S1 in2;
|
||||||
|
layout(location = 4) flat in int cond;
|
||||||
|
|
||||||
|
layout(location = 0) out float outv;
|
||||||
|
|
||||||
|
void fun1(){}
|
||||||
|
void fun2(){}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// glslang will only make OpSelect for very trivial looking expressions
|
||||||
|
|
||||||
|
float f1 = 1.0;
|
||||||
|
float f2 = 2.0;
|
||||||
|
outv = cond < 8 ? f1 : f2; // in all versions
|
||||||
|
|
||||||
|
ivec4 iv1 = ivec4(f1);
|
||||||
|
ivec4 iv2 = ivec4(f2);
|
||||||
|
outv *= (cond > 0 ? iv1 : iv2).z; // in all versions, but in 1.4 as scalar condition, not smeared ala mix()
|
||||||
|
|
||||||
|
mat3 m1 = mat3(1.0);
|
||||||
|
mat3 m2 = mat3(2.0);
|
||||||
|
outv *= (cond < 20 ? m1 : m2)[2][1]; // in 1.4, but not before
|
||||||
|
|
||||||
|
S1 fv = cond > 5 ? in1 : in2; // in 1.4, but not before
|
||||||
|
outv *= fv.a;
|
||||||
|
|
||||||
|
cond > 0 ? fun1() : fun2(); // not allowed by any version
|
||||||
|
}
|
1
gtests/Spv.FromFile.cpp
Normal file → Executable file
1
gtests/Spv.FromFile.cpp
Normal file → Executable file
@ -466,6 +466,7 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
Glsl, CompileToSpirv14Test,
|
Glsl, CompileToSpirv14Test,
|
||||||
::testing::ValuesIn(std::vector<std::string>({
|
::testing::ValuesIn(std::vector<std::string>({
|
||||||
"spv.1.4.OpEntryPoint.frag",
|
"spv.1.4.OpEntryPoint.frag",
|
||||||
|
"spv.1.4.OpSelect.frag",
|
||||||
})),
|
})),
|
||||||
FileNameAsCustomTestSuffix
|
FileNameAsCustomTestSuffix
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user