зеркало из https://github.com/stride3d/xkslang.git
glslang -> SPV: improved support for do-while/continue. Contributed by David Neto (dneto@google.com).
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@31205 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
Родитель
93dfbe1309
Коммит
593a3f7f6b
|
@ -1159,19 +1159,21 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
|||
|
||||
bool bodyOut = false;
|
||||
if (! node->testFirst()) {
|
||||
builder.endLoopHeaderWithoutTest();
|
||||
if (node->getBody()) {
|
||||
breakForLoop.push(true);
|
||||
node->getBody()->traverse(this);
|
||||
breakForLoop.pop();
|
||||
}
|
||||
bodyOut = true;
|
||||
builder.createBranchToLoopTest();
|
||||
}
|
||||
|
||||
if (node->getTest()) {
|
||||
node->getTest()->traverse(this);
|
||||
// the AST only contained the test computation, not the branch, we have to add it
|
||||
spv::Id condition = builder.accessChainLoad(TranslatePrecisionDecoration(node->getTest()->getType()));
|
||||
builder.createLoopHeaderBranch(condition);
|
||||
builder.createLoopTestBranch(condition);
|
||||
}
|
||||
|
||||
if (! bodyOut && node->getBody()) {
|
||||
|
@ -1208,7 +1210,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
|
|||
case glslang::EOpContinue:
|
||||
if (loopTerminal.top())
|
||||
loopTerminal.top()->traverse(this);
|
||||
builder.createLoopBackEdge();
|
||||
builder.createLoopContinue();
|
||||
break;
|
||||
case glslang::EOpReturn:
|
||||
if (inMain)
|
||||
|
|
|
@ -1719,6 +1719,7 @@ void Builder::makeNewLoop()
|
|||
loop.function = &getBuildPoint()->getParent();
|
||||
loop.header = new Block(getUniqueId(), *loop.function);
|
||||
loop.merge = new Block(getUniqueId(), *loop.function);
|
||||
loop.test = NULL;
|
||||
|
||||
loops.push(loop);
|
||||
|
||||
|
@ -1730,43 +1731,75 @@ void Builder::makeNewLoop()
|
|||
setBuildPoint(loop.header);
|
||||
}
|
||||
|
||||
void Builder::createLoopHeaderBranch(Id condition)
|
||||
void Builder::createLoopTestBranch(Id condition)
|
||||
{
|
||||
Loop loop = loops.top();
|
||||
Loop& loop = loops.top();
|
||||
|
||||
// If loop.test exists, then we've already generated the LoopMerge
|
||||
// for this loop.
|
||||
if (!loop.test)
|
||||
createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
|
||||
|
||||
// Branching to the "body" block will keep control inside
|
||||
// the loop.
|
||||
Block* body = new Block(getUniqueId(), *loop.function);
|
||||
createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
|
||||
createConditionalBranch(condition, body, loop.merge);
|
||||
loop.function->addBlock(body);
|
||||
setBuildPoint(body);
|
||||
}
|
||||
|
||||
// Add a back-edge (e.g "continue") for the innermost loop that you're in
|
||||
void Builder::createLoopBackEdge(bool implicit)
|
||||
void Builder::endLoopHeaderWithoutTest()
|
||||
{
|
||||
Loop loop = loops.top();
|
||||
Loop& loop = loops.top();
|
||||
|
||||
// Just branch back, and set up a block for dead code if it's a user continue
|
||||
createBranch(loop.header);
|
||||
if (! implicit)
|
||||
createAndSetNoPredecessorBlock("post-loop-continue");
|
||||
createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
|
||||
Block* body = new Block(getUniqueId(), *loop.function);
|
||||
createBranch(body);
|
||||
loop.function->addBlock(body);
|
||||
setBuildPoint(body);
|
||||
|
||||
assert(!loop.test);
|
||||
loop.test = new Block(getUniqueId(), *loop.function);
|
||||
}
|
||||
|
||||
void Builder::createBranchToLoopTest()
|
||||
{
|
||||
Loop& loop = loops.top();
|
||||
Block* testBlock = loop.test;
|
||||
assert(testBlock);
|
||||
createBranch(testBlock);
|
||||
loop.function->addBlock(testBlock);
|
||||
setBuildPoint(testBlock);
|
||||
}
|
||||
|
||||
void Builder::createLoopContinue()
|
||||
{
|
||||
Loop& loop = loops.top();
|
||||
if (loop.test)
|
||||
createBranch(loop.test);
|
||||
else
|
||||
createBranch(loop.header);
|
||||
// Set up a block for dead code.
|
||||
createAndSetNoPredecessorBlock("post-loop-continue");
|
||||
}
|
||||
|
||||
// Add an exit (e.g. "break") for the innermost loop that you're in
|
||||
void Builder::createLoopExit()
|
||||
{
|
||||
createBranch(loops.top().merge);
|
||||
// Set up a block for dead code.
|
||||
createAndSetNoPredecessorBlock("post-loop-break");
|
||||
}
|
||||
|
||||
// Close the innermost loop
|
||||
void Builder::closeLoop()
|
||||
{
|
||||
Loop& loop = loops.top();
|
||||
|
||||
// Branch back to the top
|
||||
createLoopBackEdge(true);
|
||||
createBranch(loop.header);
|
||||
|
||||
// Add the merge block and set the build point to it
|
||||
Loop loop = loops.top();
|
||||
loop.function->addBlock(loop.merge);
|
||||
setBuildPoint(loop.merge);
|
||||
|
||||
|
|
|
@ -357,13 +357,33 @@ public:
|
|||
// Start the beginning of a new loop.
|
||||
void makeNewLoop();
|
||||
|
||||
// Add the branch at the end of the loop header, and leave the build position
|
||||
// in the first block of the body.
|
||||
// 'condition' is true if should exit the loop
|
||||
void createLoopHeaderBranch(Id condition);
|
||||
// Add the branch for the loop test, based on the given condition.
|
||||
// The true branch goes to the block that remains inside the loop, and
|
||||
// the false branch goes to the loop's merge block. The builder insertion
|
||||
// point will be placed at the start of the inside-the-loop block.
|
||||
void createLoopTestBranch(Id condition);
|
||||
|
||||
// Add a back-edge (e.g "continue") for the innermost loop that you're in
|
||||
void createLoopBackEdge(bool implicit=false);
|
||||
// Finish generating the loop header block in the case where the loop test
|
||||
// is at the bottom of the loop. It will include the LoopMerge instruction
|
||||
// and a branch to the rest of the body. The loop header block must be
|
||||
// separate from the rest of the body to make room for the the two kinds
|
||||
// of *Merge instructions that might have to occur just before a branch:
|
||||
// the loop header must have a LoopMerge as its second-last instruction,
|
||||
// and the body might begin with a conditional branch, which must have its
|
||||
// own SelectionMerge instruction.
|
||||
// Also create the basic block that will contain the loop test, but don't
|
||||
// insert it into the function yet. Any "continue" constructs in this loop
|
||||
// will branch to the loop test block. The builder insertion point will be
|
||||
// placed at the start of the body block.
|
||||
void endLoopHeaderWithoutTest();
|
||||
|
||||
// Generate a branch to the loop test block. This can only be called if
|
||||
// the loop test is at the bottom of the loop. The builder insertion point
|
||||
// is left at the start of the test block.
|
||||
void createBranchToLoopTest();
|
||||
|
||||
// Add a branch to the test of the current (innermost) loop.
|
||||
void createLoopContinue();
|
||||
|
||||
// Add an exit (e.g. "break") for the innermost loop that you're in
|
||||
void createLoopExit();
|
||||
|
@ -507,8 +527,23 @@ protected:
|
|||
|
||||
// Data that needs to be kept in order to properly handle loops.
|
||||
struct Loop {
|
||||
// The header is the first block generated for the loop.
|
||||
// It dominates all the blocks in the loop, i.e. it is always
|
||||
// executed before any others.
|
||||
// If the loop test is executed before the body (as in "while" and
|
||||
// "for" loops), then the header begins with the test code.
|
||||
// Otherwise, the loop is a "do-while" loop and the header contains the
|
||||
// start of the body of the loop (if the body exists).
|
||||
Block* header;
|
||||
// The merge block marks the end of the loop. Control is transferred
|
||||
// to the merge block when either the loop test fails, or when a
|
||||
// nested "break" is encountered.
|
||||
Block* merge;
|
||||
// If not NULL, the test block is the basic block containing the loop
|
||||
// test and the conditional branch back to the header or the merge
|
||||
// block. This is created for "do-while" loops, and is the target of
|
||||
// any "continue" constructs that might exist.
|
||||
Block* test;
|
||||
Function* function;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
spv.do-simple.vert
|
||||
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
|
||||
// Module Version 99
|
||||
// Generated by (magic number): 51a00bb
|
||||
// Id's are bound by 26
|
||||
|
||||
Source GLSL 300
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4
|
||||
Name 4 "main"
|
||||
Name 9 "i"
|
||||
Name 24 "gl_VertexID"
|
||||
Name 25 "gl_InstanceID"
|
||||
Decorate 9(i) PrecisionHigh
|
||||
Decorate 24(gl_VertexID) PrecisionHigh
|
||||
Decorate 24(gl_VertexID) BuiltIn VertexId
|
||||
Decorate 24(gl_VertexID) NoStaticUse
|
||||
Decorate 25(gl_InstanceID) PrecisionHigh
|
||||
Decorate 25(gl_InstanceID) BuiltIn InstanceId
|
||||
Decorate 25(gl_InstanceID) NoStaticUse
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
7: TypeInt 32 1
|
||||
8: TypePointer Function 7(int)
|
||||
10: 7(int) Constant 0
|
||||
16: 7(int) Constant 1
|
||||
19: 7(int) Constant 10
|
||||
20: TypeBool
|
||||
23: TypePointer Input 7(int)
|
||||
24(gl_VertexID): 23(ptr) Variable Input
|
||||
25(gl_InstanceID): 23(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
9(i): 8(ptr) Variable Function
|
||||
Store 9(i) 10
|
||||
Branch 11
|
||||
11: Label
|
||||
LoopMerge 12 None
|
||||
Branch 13
|
||||
13: Label
|
||||
15: 7(int) Load 9(i)
|
||||
17: 7(int) IAdd 15 16
|
||||
Store 9(i) 17
|
||||
Branch 14
|
||||
14: Label
|
||||
18: 7(int) Load 9(i)
|
||||
21: 20(bool) SLessThan 18 19
|
||||
BranchConditional 21 22 12
|
||||
22: Label
|
||||
Branch 11
|
||||
12: Label
|
||||
Branch 6
|
||||
6: Label
|
||||
Return
|
||||
FunctionEnd
|
|
@ -0,0 +1,63 @@
|
|||
spv.for-simple.vert
|
||||
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
|
||||
// Module Version 99
|
||||
// Generated by (magic number): 51a00bb
|
||||
// Id's are bound by 26
|
||||
|
||||
Source GLSL 300
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4
|
||||
Name 4 "main"
|
||||
Name 9 "i"
|
||||
Name 18 "j"
|
||||
Name 24 "gl_VertexID"
|
||||
Name 25 "gl_InstanceID"
|
||||
Decorate 9(i) PrecisionHigh
|
||||
Decorate 18(j) PrecisionHigh
|
||||
Decorate 24(gl_VertexID) PrecisionHigh
|
||||
Decorate 24(gl_VertexID) BuiltIn VertexId
|
||||
Decorate 24(gl_VertexID) NoStaticUse
|
||||
Decorate 25(gl_InstanceID) PrecisionHigh
|
||||
Decorate 25(gl_InstanceID) BuiltIn InstanceId
|
||||
Decorate 25(gl_InstanceID) NoStaticUse
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
7: TypeInt 32 1
|
||||
8: TypePointer Function 7(int)
|
||||
10: 7(int) Constant 0
|
||||
14: 7(int) Constant 10
|
||||
15: TypeBool
|
||||
19: 7(int) Constant 12
|
||||
21: 7(int) Constant 1
|
||||
23: TypePointer Input 7(int)
|
||||
24(gl_VertexID): 23(ptr) Variable Input
|
||||
25(gl_InstanceID): 23(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
9(i): 8(ptr) Variable Function
|
||||
18(j): 8(ptr) Variable Function
|
||||
Store 9(i) 10
|
||||
Branch 11
|
||||
11: Label
|
||||
13: 7(int) Load 9(i)
|
||||
16: 15(bool) SLessThan 13 14
|
||||
LoopMerge 12 None
|
||||
BranchConditional 16 17 12
|
||||
17: Label
|
||||
Store 18(j) 19
|
||||
20: 7(int) Load 9(i)
|
||||
22: 7(int) IAdd 20 21
|
||||
Store 9(i) 22
|
||||
Branch 11
|
||||
12: Label
|
||||
Branch 6
|
||||
6: Label
|
||||
Return
|
||||
FunctionEnd
|
|
@ -0,0 +1,99 @@
|
|||
spv.while-continue-break.vert
|
||||
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
|
||||
// Module Version 99
|
||||
// Generated by (magic number): 51a00bb
|
||||
// Id's are bound by 43
|
||||
|
||||
Source GLSL 300
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4
|
||||
Name 4 "main"
|
||||
Name 9 "i"
|
||||
Name 18 "A"
|
||||
Name 26 "B"
|
||||
Name 28 "C"
|
||||
Name 38 "D"
|
||||
Name 41 "gl_VertexID"
|
||||
Name 42 "gl_InstanceID"
|
||||
Decorate 9(i) PrecisionHigh
|
||||
Decorate 18(A) PrecisionHigh
|
||||
Decorate 26(B) PrecisionHigh
|
||||
Decorate 28(C) PrecisionHigh
|
||||
Decorate 38(D) PrecisionHigh
|
||||
Decorate 41(gl_VertexID) PrecisionHigh
|
||||
Decorate 41(gl_VertexID) BuiltIn VertexId
|
||||
Decorate 41(gl_VertexID) NoStaticUse
|
||||
Decorate 42(gl_InstanceID) PrecisionHigh
|
||||
Decorate 42(gl_InstanceID) BuiltIn InstanceId
|
||||
Decorate 42(gl_InstanceID) NoStaticUse
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
7: TypeInt 32 1
|
||||
8: TypePointer Function 7(int)
|
||||
10: 7(int) Constant 0
|
||||
14: 7(int) Constant 10
|
||||
15: TypeBool
|
||||
19: 7(int) Constant 1
|
||||
21: 7(int) Constant 2
|
||||
30: 7(int) Constant 5
|
||||
39: 7(int) Constant 3
|
||||
40: TypePointer Input 7(int)
|
||||
41(gl_VertexID): 40(ptr) Variable Input
|
||||
42(gl_InstanceID): 40(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
9(i): 8(ptr) Variable Function
|
||||
18(A): 8(ptr) Variable Function
|
||||
26(B): 8(ptr) Variable Function
|
||||
28(C): 8(ptr) Variable Function
|
||||
38(D): 8(ptr) Variable Function
|
||||
Store 9(i) 10
|
||||
Branch 11
|
||||
11: Label
|
||||
13: 7(int) Load 9(i)
|
||||
16: 15(bool) SLessThan 13 14
|
||||
LoopMerge 12 None
|
||||
BranchConditional 16 17 12
|
||||
17: Label
|
||||
Store 18(A) 19
|
||||
20: 7(int) Load 9(i)
|
||||
22: 7(int) SMod 20 21
|
||||
23: 15(bool) IEqual 22 10
|
||||
SelectionMerge 25 None
|
||||
BranchConditional 23 24 25
|
||||
24: Label
|
||||
Store 26(B) 21
|
||||
Branch 11
|
||||
27: Label
|
||||
Store 28(C) 21
|
||||
Branch 25
|
||||
25: Label
|
||||
29: 7(int) Load 9(i)
|
||||
31: 7(int) SMod 29 30
|
||||
32: 15(bool) IEqual 31 10
|
||||
SelectionMerge 34 None
|
||||
BranchConditional 32 33 34
|
||||
33: Label
|
||||
Store 26(B) 21
|
||||
Branch 12
|
||||
35: Label
|
||||
Store 28(C) 21
|
||||
Branch 34
|
||||
34: Label
|
||||
36: 7(int) Load 9(i)
|
||||
37: 7(int) IAdd 36 19
|
||||
Store 9(i) 37
|
||||
Branch 11
|
||||
12: Label
|
||||
Store 38(D) 39
|
||||
Branch 6
|
||||
6: Label
|
||||
Return
|
||||
FunctionEnd
|
|
@ -0,0 +1,58 @@
|
|||
spv.while-simple.vert
|
||||
|
||||
|
||||
|
||||
Linked vertex stage:
|
||||
|
||||
|
||||
|
||||
// Module Version 99
|
||||
// Generated by (magic number): 51a00bb
|
||||
// Id's are bound by 24
|
||||
|
||||
Source GLSL 300
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Vertex 4
|
||||
Name 4 "main"
|
||||
Name 9 "i"
|
||||
Name 22 "gl_VertexID"
|
||||
Name 23 "gl_InstanceID"
|
||||
Decorate 9(i) PrecisionHigh
|
||||
Decorate 22(gl_VertexID) PrecisionHigh
|
||||
Decorate 22(gl_VertexID) BuiltIn VertexId
|
||||
Decorate 22(gl_VertexID) NoStaticUse
|
||||
Decorate 23(gl_InstanceID) PrecisionHigh
|
||||
Decorate 23(gl_InstanceID) BuiltIn InstanceId
|
||||
Decorate 23(gl_InstanceID) NoStaticUse
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
7: TypeInt 32 1
|
||||
8: TypePointer Function 7(int)
|
||||
10: 7(int) Constant 0
|
||||
14: 7(int) Constant 10
|
||||
15: TypeBool
|
||||
19: 7(int) Constant 1
|
||||
21: TypePointer Input 7(int)
|
||||
22(gl_VertexID): 21(ptr) Variable Input
|
||||
23(gl_InstanceID): 21(ptr) Variable Input
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
9(i): 8(ptr) Variable Function
|
||||
Store 9(i) 10
|
||||
Branch 11
|
||||
11: Label
|
||||
13: 7(int) Load 9(i)
|
||||
16: 15(bool) SLessThan 13 14
|
||||
LoopMerge 12 None
|
||||
BranchConditional 16 17 12
|
||||
17: Label
|
||||
18: 7(int) Load 9(i)
|
||||
20: 7(int) IAdd 18 19
|
||||
Store 9(i) 20
|
||||
Branch 11
|
||||
12: Label
|
||||
Branch 6
|
||||
6: Label
|
||||
Return
|
||||
FunctionEnd
|
|
@ -36,6 +36,16 @@ if [ -a localtestlist ]
|
|||
done < localtestlist
|
||||
fi
|
||||
|
||||
#
|
||||
# SPIR-V code generation tests
|
||||
#
|
||||
grep -v "^#" test-spirv-list | while read t; do
|
||||
echo Running SPIR-V $t...
|
||||
b=`basename $t`
|
||||
$EXE -H $t > $TARGETDIR/$b.out
|
||||
diff -b $BASEDIR/$b.out $TARGETDIR/$b.out
|
||||
done
|
||||
|
||||
#
|
||||
# grouped shaders for bulk (faster) tests
|
||||
#
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i = 0;
|
||||
do {
|
||||
i++;
|
||||
} while(i<10);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i = 0;
|
||||
int A, B, C, D, E, F, G;
|
||||
do {
|
||||
A = 0;
|
||||
if (i == 2) {
|
||||
B = 1;
|
||||
continue;
|
||||
C = 2;
|
||||
}
|
||||
if (i == 5) {
|
||||
D = 3;
|
||||
break;
|
||||
E = 42;
|
||||
}
|
||||
F = 99;
|
||||
} while (++i < 19);
|
||||
G = 12;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i;
|
||||
int A, B, C, D, E, F, G;
|
||||
for (i=0; i < 10 ; i++) {
|
||||
A = 1;
|
||||
if (i%2 ==0) {
|
||||
B = 1;
|
||||
continue;
|
||||
C = 1;
|
||||
}
|
||||
if (i%3 == 0) {
|
||||
D = 1;
|
||||
break;
|
||||
E = 1;
|
||||
}
|
||||
F = 12;
|
||||
}
|
||||
G = 99;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i;
|
||||
int j;
|
||||
for (i=0; i < 10 ; i++) {
|
||||
j = 12;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i = 0;
|
||||
int A, B, C, D;
|
||||
while (i<10) {
|
||||
A = 1;
|
||||
if (i%2 == 0) {
|
||||
B = 2;
|
||||
continue;
|
||||
C = 2;
|
||||
}
|
||||
if (i%5 == 0) {
|
||||
B = 2;
|
||||
break;
|
||||
C = 2;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
D = 3;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#version 300 es
|
||||
void main() {
|
||||
int i = 0;
|
||||
while (i<10) {
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
# Test looping constructs.
|
||||
# No tests yet for making sure break and continue from a nested loop
|
||||
# goes to the innermost target.
|
||||
spv.do-simple.vert
|
||||
spv.do-while-continue-break.vert
|
||||
spv.for-continue-break.vert
|
||||
spv.for-simple.vert
|
||||
spv.while-continue-break.vert
|
||||
spv.while-simple.vert
|
Загрузка…
Ссылка в новой задаче