mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-12 21:20:06 +00:00
HLSL: implement [unroll] and [loop] attributes
This adds infrastructure suitable for any front end to create SPIR-V loop control flags. The only current front end doing so is HLSL. [unroll] turns into spv::LoopControlUnrollMask [loop] turns into spv::LoopControlDontUnrollMask no specification means spv::LoopControlMaskNone
This commit is contained in:
parent
de1cc06c1d
commit
f1709e7146
@ -122,6 +122,7 @@ protected:
|
|||||||
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
||||||
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
|
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
|
||||||
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
|
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
|
||||||
|
spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
|
||||||
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
||||||
spv::Id getSampledType(const glslang::TSampler&);
|
spv::Id getSampledType(const glslang::TSampler&);
|
||||||
spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
|
spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
|
||||||
@ -767,6 +768,18 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
|
||||||
|
{
|
||||||
|
switch (loopControl) {
|
||||||
|
case glslang::ELoopControlNone: return spv::LoopControlMaskNone;
|
||||||
|
case glslang::ELoopControlUnroll: return spv::LoopControlUnrollMask;
|
||||||
|
case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
|
||||||
|
// TODO: DependencyInfinite
|
||||||
|
// TODO: DependencyLength
|
||||||
|
default: return spv::LoopControlMaskNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether or not the given type is something that should be tied to a
|
// Return whether or not the given type is something that should be tied to a
|
||||||
// descriptor set.
|
// descriptor set.
|
||||||
bool IsDescriptorResource(const glslang::TType& type)
|
bool IsDescriptorResource(const glslang::TType& type)
|
||||||
@ -1960,6 +1973,12 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
|||||||
{
|
{
|
||||||
auto blocks = builder.makeNewLoop();
|
auto blocks = builder.makeNewLoop();
|
||||||
builder.createBranch(&blocks.head);
|
builder.createBranch(&blocks.head);
|
||||||
|
|
||||||
|
// Loop control:
|
||||||
|
const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
|
||||||
|
|
||||||
|
// TODO: dependency length
|
||||||
|
|
||||||
// Spec requires back edges to target header blocks, and every header block
|
// Spec requires back edges to target header blocks, and every header block
|
||||||
// must dominate its merge block. Make a header block first to ensure these
|
// must dominate its merge block. Make a header block first to ensure these
|
||||||
// conditions are met. By definition, it will contain OpLoopMerge, followed
|
// conditions are met. By definition, it will contain OpLoopMerge, followed
|
||||||
@ -1967,7 +1986,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
|||||||
// instructions in it, since the body/test may have arbitrary instructions,
|
// instructions in it, since the body/test may have arbitrary instructions,
|
||||||
// including merges of its own.
|
// including merges of its own.
|
||||||
builder.setBuildPoint(&blocks.head);
|
builder.setBuildPoint(&blocks.head);
|
||||||
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
|
builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
|
||||||
if (node->testFirst() && node->getTest()) {
|
if (node->testFirst() && node->getTest()) {
|
||||||
spv::Block& test = builder.makeNewBlock();
|
spv::Block& test = builder.makeNewBlock();
|
||||||
builder.createBranch(&test);
|
builder.createBranch(&test);
|
||||||
|
@ -132,7 +132,7 @@ local_size = (4, 6, 8)
|
|||||||
Store 13(x) 14
|
Store 13(x) 14
|
||||||
Branch 15
|
Branch 15
|
||||||
15: Label
|
15: Label
|
||||||
LoopMerge 17 18 None
|
LoopMerge 17 18 Unroll
|
||||||
Branch 19
|
Branch 19
|
||||||
19: Label
|
19: Label
|
||||||
20: 11(int) Load 13(x)
|
20: 11(int) Load 13(x)
|
||||||
|
@ -194,7 +194,7 @@ gl_FragCoord origin is upper left
|
|||||||
12: Label
|
12: Label
|
||||||
Branch 13
|
Branch 13
|
||||||
13: Label
|
13: Label
|
||||||
LoopMerge 15 16 None
|
LoopMerge 15 16 Unroll
|
||||||
Branch 14
|
Branch 14
|
||||||
14: Label
|
14: Label
|
||||||
Branch 16
|
Branch 16
|
||||||
@ -203,7 +203,7 @@ gl_FragCoord origin is upper left
|
|||||||
15: Label
|
15: Label
|
||||||
Branch 19
|
Branch 19
|
||||||
19: Label
|
19: Label
|
||||||
LoopMerge 21 22 None
|
LoopMerge 21 22 Unroll
|
||||||
Branch 20
|
Branch 20
|
||||||
20: Label
|
20: Label
|
||||||
Branch 22
|
Branch 22
|
||||||
|
@ -338,7 +338,7 @@ gl_FragCoord origin is upper left
|
|||||||
23: Label
|
23: Label
|
||||||
Branch 25
|
Branch 25
|
||||||
25: Label
|
25: Label
|
||||||
LoopMerge 27 28 None
|
LoopMerge 27 28 Unroll
|
||||||
Branch 29
|
Branch 29
|
||||||
29: Label
|
29: Label
|
||||||
30: 7(fvec4) Load 10(input)
|
30: 7(fvec4) Load 10(input)
|
||||||
|
233
Test/baseResults/hlsl.loopattr.frag.out
Normal file
233
Test/baseResults/hlsl.loopattr.frag.out
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
hlsl.loopattr.frag
|
||||||
|
Shader version: 500
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:3 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:3 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Sequence
|
||||||
|
0:5 move second child to first child ( temp int)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:5 Constant:
|
||||||
|
0:5 0 (const int)
|
||||||
|
0:5 Loop with condition tested first
|
||||||
|
0:5 Loop Condition
|
||||||
|
0:5 Compare Less Than ( temp bool)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:5 Constant:
|
||||||
|
0:5 5 (const int)
|
||||||
|
0:5 No loop body
|
||||||
|
0:5 Loop Terminal Expression
|
||||||
|
0:5 Pre-Increment ( temp int)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 move second child to first child ( temp int)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 0 (const int)
|
||||||
|
0:8 Loop with condition tested first
|
||||||
|
0:8 Loop Condition
|
||||||
|
0:8 Compare Less Than ( temp bool)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 5 (const int)
|
||||||
|
0:8 No loop body
|
||||||
|
0:8 Loop Terminal Expression
|
||||||
|
0:8 Pre-Increment ( temp int)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp int)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 0 (const int)
|
||||||
|
0:11 Loop with condition tested first
|
||||||
|
0:11 Loop Condition
|
||||||
|
0:11 Compare Less Than ( temp bool)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 5 (const int)
|
||||||
|
0:11 No loop body
|
||||||
|
0:11 Loop Terminal Expression
|
||||||
|
0:11 Pre-Increment ( temp int)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:13 Branch: Return with expression
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:3 Function Definition: main( ( temp void)
|
||||||
|
0:3 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:3 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:3 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
|
||||||
|
Linked fragment stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 500
|
||||||
|
gl_FragCoord origin is upper left
|
||||||
|
0:? Sequence
|
||||||
|
0:3 Function Definition: @main( ( temp 4-component vector of float)
|
||||||
|
0:3 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:5 Sequence
|
||||||
|
0:5 move second child to first child ( temp int)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:5 Constant:
|
||||||
|
0:5 0 (const int)
|
||||||
|
0:5 Loop with condition tested first
|
||||||
|
0:5 Loop Condition
|
||||||
|
0:5 Compare Less Than ( temp bool)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:5 Constant:
|
||||||
|
0:5 5 (const int)
|
||||||
|
0:5 No loop body
|
||||||
|
0:5 Loop Terminal Expression
|
||||||
|
0:5 Pre-Increment ( temp int)
|
||||||
|
0:5 'x' ( temp int)
|
||||||
|
0:8 Sequence
|
||||||
|
0:8 move second child to first child ( temp int)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 0 (const int)
|
||||||
|
0:8 Loop with condition tested first
|
||||||
|
0:8 Loop Condition
|
||||||
|
0:8 Compare Less Than ( temp bool)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:8 Constant:
|
||||||
|
0:8 5 (const int)
|
||||||
|
0:8 No loop body
|
||||||
|
0:8 Loop Terminal Expression
|
||||||
|
0:8 Pre-Increment ( temp int)
|
||||||
|
0:8 'y' ( temp int)
|
||||||
|
0:11 Sequence
|
||||||
|
0:11 move second child to first child ( temp int)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 0 (const int)
|
||||||
|
0:11 Loop with condition tested first
|
||||||
|
0:11 Loop Condition
|
||||||
|
0:11 Compare Less Than ( temp bool)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:11 Constant:
|
||||||
|
0:11 5 (const int)
|
||||||
|
0:11 No loop body
|
||||||
|
0:11 Loop Terminal Expression
|
||||||
|
0:11 Pre-Increment ( temp int)
|
||||||
|
0:11 'z' ( temp int)
|
||||||
|
0:13 Branch: Return with expression
|
||||||
|
0:13 Constant:
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:13 0.000000
|
||||||
|
0:3 Function Definition: main( ( temp void)
|
||||||
|
0:3 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:3 move second child to first child ( temp 4-component vector of float)
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
0:3 Function Call: @main( ( temp 4-component vector of float)
|
||||||
|
0:? Linker Objects
|
||||||
|
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80001
|
||||||
|
// Id's are bound by 54
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Fragment 4 "main" 52
|
||||||
|
ExecutionMode 4 OriginUpperLeft
|
||||||
|
Source HLSL 500
|
||||||
|
Name 4 "main"
|
||||||
|
Name 9 "@main("
|
||||||
|
Name 13 "x"
|
||||||
|
Name 27 "y"
|
||||||
|
Name 37 "z"
|
||||||
|
Name 52 "@entryPointOutput"
|
||||||
|
Decorate 52(@entryPointOutput) Location 0
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeFloat 32
|
||||||
|
7: TypeVector 6(float) 4
|
||||||
|
8: TypeFunction 7(fvec4)
|
||||||
|
11: TypeInt 32 1
|
||||||
|
12: TypePointer Function 11(int)
|
||||||
|
14: 11(int) Constant 0
|
||||||
|
21: 11(int) Constant 5
|
||||||
|
22: TypeBool
|
||||||
|
25: 11(int) Constant 1
|
||||||
|
47: 6(float) Constant 0
|
||||||
|
48: 7(fvec4) ConstantComposite 47 47 47 47
|
||||||
|
51: TypePointer Output 7(fvec4)
|
||||||
|
52(@entryPointOutput): 51(ptr) Variable Output
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
53: 7(fvec4) FunctionCall 9(@main()
|
||||||
|
Store 52(@entryPointOutput) 53
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
9(@main(): 7(fvec4) Function None 8
|
||||||
|
10: Label
|
||||||
|
13(x): 12(ptr) Variable Function
|
||||||
|
27(y): 12(ptr) Variable Function
|
||||||
|
37(z): 12(ptr) Variable Function
|
||||||
|
Store 13(x) 14
|
||||||
|
Branch 15
|
||||||
|
15: Label
|
||||||
|
LoopMerge 17 18 Unroll
|
||||||
|
Branch 19
|
||||||
|
19: Label
|
||||||
|
20: 11(int) Load 13(x)
|
||||||
|
23: 22(bool) SLessThan 20 21
|
||||||
|
BranchConditional 23 16 17
|
||||||
|
16: Label
|
||||||
|
Branch 18
|
||||||
|
18: Label
|
||||||
|
24: 11(int) Load 13(x)
|
||||||
|
26: 11(int) IAdd 24 25
|
||||||
|
Store 13(x) 26
|
||||||
|
Branch 15
|
||||||
|
17: Label
|
||||||
|
Store 27(y) 14
|
||||||
|
Branch 28
|
||||||
|
28: Label
|
||||||
|
LoopMerge 30 31 DontUnroll
|
||||||
|
Branch 32
|
||||||
|
32: Label
|
||||||
|
33: 11(int) Load 27(y)
|
||||||
|
34: 22(bool) SLessThan 33 21
|
||||||
|
BranchConditional 34 29 30
|
||||||
|
29: Label
|
||||||
|
Branch 31
|
||||||
|
31: Label
|
||||||
|
35: 11(int) Load 27(y)
|
||||||
|
36: 11(int) IAdd 35 25
|
||||||
|
Store 27(y) 36
|
||||||
|
Branch 28
|
||||||
|
30: Label
|
||||||
|
Store 37(z) 14
|
||||||
|
Branch 38
|
||||||
|
38: Label
|
||||||
|
LoopMerge 40 41 None
|
||||||
|
Branch 42
|
||||||
|
42: Label
|
||||||
|
43: 11(int) Load 37(z)
|
||||||
|
44: 22(bool) SLessThan 43 21
|
||||||
|
BranchConditional 44 39 40
|
||||||
|
39: Label
|
||||||
|
Branch 41
|
||||||
|
41: Label
|
||||||
|
45: 11(int) Load 37(z)
|
||||||
|
46: 11(int) IAdd 45 25
|
||||||
|
Store 37(z) 46
|
||||||
|
Branch 38
|
||||||
|
40: Label
|
||||||
|
ReturnValue 48
|
||||||
|
FunctionEnd
|
@ -171,7 +171,7 @@ gl_FragCoord origin is upper left
|
|||||||
28: Label
|
28: Label
|
||||||
Branch 32
|
Branch 32
|
||||||
32: Label
|
32: Label
|
||||||
LoopMerge 34 35 None
|
LoopMerge 34 35 Unroll
|
||||||
Branch 36
|
Branch 36
|
||||||
36: Label
|
36: Label
|
||||||
BranchConditional 31 33 34
|
BranchConditional 31 33 34
|
||||||
|
14
Test/hlsl.loopattr.frag
Normal file
14
Test/hlsl.loopattr.frag
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
float4 main() : SV_Target0
|
||||||
|
{
|
||||||
|
// Unroll hint
|
||||||
|
[unroll(5) ] for (int x=0; x<5; ++x);
|
||||||
|
|
||||||
|
// Don't unroll hint
|
||||||
|
[loop] for (int y=0; y<5; ++y);
|
||||||
|
|
||||||
|
// No hint
|
||||||
|
for (int z=0; z<5; ++z);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -758,6 +758,15 @@ protected:
|
|||||||
TType type;
|
TType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Loop control hints
|
||||||
|
//
|
||||||
|
enum TLoopControl {
|
||||||
|
ELoopControlNone,
|
||||||
|
ELoopControlUnroll,
|
||||||
|
ELoopControlDontUnroll,
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle for, do-while, and while loops.
|
// Handle for, do-while, and while loops.
|
||||||
//
|
//
|
||||||
@ -767,17 +776,25 @@ public:
|
|||||||
body(aBody),
|
body(aBody),
|
||||||
test(aTest),
|
test(aTest),
|
||||||
terminal(aTerminal),
|
terminal(aTerminal),
|
||||||
first(testFirst) { }
|
first(testFirst),
|
||||||
|
control(ELoopControlNone)
|
||||||
|
{ }
|
||||||
|
|
||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
TIntermNode* getBody() const { return body; }
|
TIntermNode* getBody() const { return body; }
|
||||||
TIntermTyped* getTest() const { return test; }
|
TIntermTyped* getTest() const { return test; }
|
||||||
TIntermTyped* getTerminal() const { return terminal; }
|
TIntermTyped* getTerminal() const { return terminal; }
|
||||||
bool testFirst() const { return first; }
|
bool testFirst() const { return first; }
|
||||||
|
|
||||||
|
void setLoopControl(TLoopControl c) { control = c; }
|
||||||
|
TLoopControl getLoopControl() const { return control; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TIntermNode* body; // code to loop over
|
TIntermNode* body; // code to loop over
|
||||||
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
|
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
|
||||||
TIntermTyped* terminal; // exists for for-loops
|
TIntermTyped* terminal; // exists for for-loops
|
||||||
bool first; // true for while and for, not for do-while
|
bool first; // true for while and for, not for do-while
|
||||||
|
TLoopControl control; // loop control hint
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1630,10 +1630,11 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
|
|||||||
//
|
//
|
||||||
// Create while and do-while loop nodes.
|
// Create while and do-while loop nodes.
|
||||||
//
|
//
|
||||||
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
|
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
|
||||||
{
|
{
|
||||||
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
|
node->setLoopControl(control);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -1641,10 +1642,11 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
|
|||||||
//
|
//
|
||||||
// Create a for-loop sequence.
|
// Create a for-loop sequence.
|
||||||
//
|
//
|
||||||
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
|
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
|
||||||
{
|
{
|
||||||
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
|
node->setLoopControl(control);
|
||||||
|
|
||||||
// make a sequence of the initializer and statement
|
// make a sequence of the initializer and statement
|
||||||
TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
|
TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
|
||||||
|
@ -283,8 +283,8 @@ public:
|
|||||||
TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
|
TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
|
||||||
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
|
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
|
||||||
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
||||||
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
|
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
|
||||||
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
|
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
|
||||||
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
|
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
|
||||||
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
||||||
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
|
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
|
||||||
|
@ -175,6 +175,7 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
{"hlsl.logical.binary.vec.frag", "main"},
|
{"hlsl.logical.binary.vec.frag", "main"},
|
||||||
{"hlsl.logicalConvert.frag", "main"},
|
{"hlsl.logicalConvert.frag", "main"},
|
||||||
{"hlsl.logical.unary.frag", "main"},
|
{"hlsl.logical.unary.frag", "main"},
|
||||||
|
{"hlsl.loopattr.frag", "main"},
|
||||||
{"hlsl.namespace.frag", "main"},
|
{"hlsl.namespace.frag", "main"},
|
||||||
{"hlsl.nonint-index.frag", "main"},
|
{"hlsl.nonint-index.frag", "main"},
|
||||||
{"hlsl.matNx1.frag", "main"},
|
{"hlsl.matNx1.frag", "main"},
|
||||||
|
@ -80,6 +80,8 @@ namespace glslang {
|
|||||||
return EatPatchConstantFunc;
|
return EatPatchConstantFunc;
|
||||||
else if (lowername == "unroll")
|
else if (lowername == "unroll")
|
||||||
return EatUnroll;
|
return EatUnroll;
|
||||||
|
else if (lowername == "loop")
|
||||||
|
return EatLoop;
|
||||||
else
|
else
|
||||||
return EatNone;
|
return EatNone;
|
||||||
}
|
}
|
||||||
@ -107,4 +109,10 @@ namespace glslang {
|
|||||||
return (entry == attributes.end()) ? nullptr : entry->second;
|
return (entry == attributes.end()) ? nullptr : entry->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// True if entry exists in map (even if value is nullptr)
|
||||||
|
bool TAttributeMap::contains(TAttributeType attr) const
|
||||||
|
{
|
||||||
|
return attributes.find(attr) != attributes.end();
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
@ -62,6 +62,7 @@ namespace glslang {
|
|||||||
EatPatchConstantFunc,
|
EatPatchConstantFunc,
|
||||||
EatPatchSize,
|
EatPatchSize,
|
||||||
EatUnroll,
|
EatUnroll,
|
||||||
|
EatLoop,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +87,9 @@ namespace glslang {
|
|||||||
// Const lookup: search for (but do not modify) the attribute in the map.
|
// Const lookup: search for (but do not modify) the attribute in the map.
|
||||||
const TIntermAggregate* operator[](TAttributeType) const;
|
const TIntermAggregate* operator[](TAttributeType) const;
|
||||||
|
|
||||||
|
// True if entry exists in map (even if value is nullptr)
|
||||||
|
bool contains(TAttributeType) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Find an attribute enum given its name.
|
// Find an attribute enum given its name.
|
||||||
static TAttributeType attributeFromName(const TString&);
|
static TAttributeType attributeFromName(const TString&);
|
||||||
|
@ -3127,7 +3127,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
|
|||||||
case EHTokFor:
|
case EHTokFor:
|
||||||
case EHTokDo:
|
case EHTokDo:
|
||||||
case EHTokWhile:
|
case EHTokWhile:
|
||||||
return acceptIterationStatement(statement);
|
return acceptIterationStatement(statement, attributes);
|
||||||
|
|
||||||
case EHTokContinue:
|
case EHTokContinue:
|
||||||
case EHTokBreak:
|
case EHTokBreak:
|
||||||
@ -3336,7 +3336,7 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
|
|||||||
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
|
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
|
||||||
//
|
//
|
||||||
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
|
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
|
||||||
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
|
||||||
{
|
{
|
||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
TIntermTyped* condition = nullptr;
|
TIntermTyped* condition = nullptr;
|
||||||
@ -3347,6 +3347,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
|||||||
// WHILE or DO or FOR
|
// WHILE or DO or FOR
|
||||||
advanceToken();
|
advanceToken();
|
||||||
|
|
||||||
|
const TLoopControl control = parseContext.handleLoopControl(attributes);
|
||||||
|
|
||||||
switch (loop) {
|
switch (loop) {
|
||||||
case EHTokWhile:
|
case EHTokWhile:
|
||||||
// so that something declared in the condition is scoped to the lifetime
|
// so that something declared in the condition is scoped to the lifetime
|
||||||
@ -3370,7 +3372,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
|||||||
parseContext.unnestLooping();
|
parseContext.unnestLooping();
|
||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
|
|
||||||
statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
|
statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -3402,7 +3404,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
|||||||
|
|
||||||
parseContext.unnestLooping();
|
parseContext.unnestLooping();
|
||||||
|
|
||||||
statement = intermediate.addLoop(statement, condition, 0, false, loc);
|
statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -3451,7 +3453,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc);
|
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
|
||||||
|
|
||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
parseContext.unnestLooping();
|
parseContext.unnestLooping();
|
||||||
|
@ -116,7 +116,7 @@ namespace glslang {
|
|||||||
void acceptAttributes(TAttributeMap&);
|
void acceptAttributes(TAttributeMap&);
|
||||||
bool acceptSelectionStatement(TIntermNode*&);
|
bool acceptSelectionStatement(TIntermNode*&);
|
||||||
bool acceptSwitchStatement(TIntermNode*&);
|
bool acceptSwitchStatement(TIntermNode*&);
|
||||||
bool acceptIterationStatement(TIntermNode*&);
|
bool acceptIterationStatement(TIntermNode*&, const TAttributeMap&);
|
||||||
bool acceptJumpStatement(TIntermNode*&);
|
bool acceptJumpStatement(TIntermNode*&);
|
||||||
bool acceptCaseLabel(TIntermNode*&);
|
bool acceptCaseLabel(TIntermNode*&);
|
||||||
bool acceptDefaultLabel(TIntermNode*&);
|
bool acceptDefaultLabel(TIntermNode*&);
|
||||||
|
@ -7568,6 +7568,20 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Loop hints
|
||||||
|
//
|
||||||
|
TLoopControl HlslParseContext::handleLoopControl(const TAttributeMap& attributes) const
|
||||||
|
{
|
||||||
|
if (attributes.contains(EatUnroll))
|
||||||
|
return ELoopControlUnroll;
|
||||||
|
else if (attributes.contains(EatLoop))
|
||||||
|
return ELoopControlDontUnroll;
|
||||||
|
else
|
||||||
|
return ELoopControlNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Updating default qualifier for the case of a declaration with just a qualifier,
|
// Updating default qualifier for the case of a declaration with just a qualifier,
|
||||||
// no type, block, or identifier.
|
// no type, block, or identifier.
|
||||||
|
@ -192,6 +192,9 @@ public:
|
|||||||
bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
||||||
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
||||||
|
|
||||||
|
// Determine loop control from attributes
|
||||||
|
TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
|
||||||
|
|
||||||
// Potentially rename shader entry point function
|
// Potentially rename shader entry point function
|
||||||
void renameShaderFunction(const TString*& name) const;
|
void renameShaderFunction(const TString*& name) const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user