Merge pull request #1378 from LoopDawg/append-decl-order
HLSL: Allow stream output Append() method after entry point.
This commit is contained in:
commit
90de7a7495
5 changed files with 275 additions and 11 deletions
212
Test/baseResults/hlsl.tristream-append.geom.out
Normal file
212
Test/baseResults/hlsl.tristream-append.geom.out
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
hlsl.tristream-append.geom
|
||||||
|
Shader version: 500
|
||||||
|
invocations = -1
|
||||||
|
max_vertices = 3
|
||||||
|
input primitive = triangles
|
||||||
|
output primitive = triangle_strip
|
||||||
|
0:? Sequence
|
||||||
|
0:8 Function Definition: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:8 Function Parameters:
|
||||||
|
0:8 'output' ( in structure{})
|
||||||
|
0:8 'TriStream' ( out structure{})
|
||||||
|
0:? Sequence
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child ( temp structure{})
|
||||||
|
0:9 'TriStream' ( out structure{})
|
||||||
|
0:9 'output' ( in structure{})
|
||||||
|
0:9 EmitVertex ( temp void)
|
||||||
|
0:14 Function Definition: @main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:14 Function Parameters:
|
||||||
|
0:14 'input' ( in 3-element array of structure{})
|
||||||
|
0:14 'TriStream' ( out structure{})
|
||||||
|
0:? Sequence
|
||||||
|
0:15 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:15 direct index ( temp structure{})
|
||||||
|
0:15 'input' ( in 3-element array of structure{})
|
||||||
|
0:15 Constant:
|
||||||
|
0:15 0 (const int)
|
||||||
|
0:15 'TriStream' ( out structure{})
|
||||||
|
0:16 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:16 direct index ( temp structure{})
|
||||||
|
0:16 'input' ( in 3-element array of structure{})
|
||||||
|
0:16 Constant:
|
||||||
|
0:16 1 (const int)
|
||||||
|
0:16 'TriStream' ( out structure{})
|
||||||
|
0:17 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:17 direct index ( temp structure{})
|
||||||
|
0:17 'input' ( in 3-element array of structure{})
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 2 (const int)
|
||||||
|
0:17 'TriStream' ( out structure{})
|
||||||
|
0:14 Function Definition: main( ( temp void)
|
||||||
|
0:14 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:14 move second child to first child ( temp 3-element array of structure{})
|
||||||
|
0:? 'input' ( temp 3-element array of structure{})
|
||||||
|
0:? 'input' ( in 3-element array of structure{})
|
||||||
|
0:14 Function Call: @main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:? 'input' ( temp 3-element array of structure{})
|
||||||
|
0:? 'TriStream' ( temp structure{})
|
||||||
|
0:? Linker Objects
|
||||||
|
|
||||||
|
|
||||||
|
Linked geometry stage:
|
||||||
|
|
||||||
|
|
||||||
|
Shader version: 500
|
||||||
|
invocations = 1
|
||||||
|
max_vertices = 3
|
||||||
|
input primitive = triangles
|
||||||
|
output primitive = triangle_strip
|
||||||
|
0:? Sequence
|
||||||
|
0:8 Function Definition: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:8 Function Parameters:
|
||||||
|
0:8 'output' ( in structure{})
|
||||||
|
0:8 'TriStream' ( out structure{})
|
||||||
|
0:? Sequence
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 Sequence
|
||||||
|
0:9 move second child to first child ( temp structure{})
|
||||||
|
0:9 'TriStream' ( out structure{})
|
||||||
|
0:9 'output' ( in structure{})
|
||||||
|
0:9 EmitVertex ( temp void)
|
||||||
|
0:14 Function Definition: @main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:14 Function Parameters:
|
||||||
|
0:14 'input' ( in 3-element array of structure{})
|
||||||
|
0:14 'TriStream' ( out structure{})
|
||||||
|
0:? Sequence
|
||||||
|
0:15 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:15 direct index ( temp structure{})
|
||||||
|
0:15 'input' ( in 3-element array of structure{})
|
||||||
|
0:15 Constant:
|
||||||
|
0:15 0 (const int)
|
||||||
|
0:15 'TriStream' ( out structure{})
|
||||||
|
0:16 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:16 direct index ( temp structure{})
|
||||||
|
0:16 'input' ( in 3-element array of structure{})
|
||||||
|
0:16 Constant:
|
||||||
|
0:16 1 (const int)
|
||||||
|
0:16 'TriStream' ( out structure{})
|
||||||
|
0:17 Function Call: EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:17 direct index ( temp structure{})
|
||||||
|
0:17 'input' ( in 3-element array of structure{})
|
||||||
|
0:17 Constant:
|
||||||
|
0:17 2 (const int)
|
||||||
|
0:17 'TriStream' ( out structure{})
|
||||||
|
0:14 Function Definition: main( ( temp void)
|
||||||
|
0:14 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:14 move second child to first child ( temp 3-element array of structure{})
|
||||||
|
0:? 'input' ( temp 3-element array of structure{})
|
||||||
|
0:? 'input' ( in 3-element array of structure{})
|
||||||
|
0:14 Function Call: @main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1; ( temp void)
|
||||||
|
0:? 'input' ( temp 3-element array of structure{})
|
||||||
|
0:? 'TriStream' ( temp structure{})
|
||||||
|
0:? Linker Objects
|
||||||
|
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 80006
|
||||||
|
// Id's are bound by 57
|
||||||
|
|
||||||
|
Capability Geometry
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Geometry 4 "main"
|
||||||
|
ExecutionMode 4 Triangles
|
||||||
|
ExecutionMode 4 Invocations 1
|
||||||
|
ExecutionMode 4 OutputTriangleStrip
|
||||||
|
ExecutionMode 4 OutputVertices 3
|
||||||
|
Source HLSL 500
|
||||||
|
Name 4 "main"
|
||||||
|
Name 6 "GSPS_INPUT"
|
||||||
|
Name 11 "EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1;"
|
||||||
|
Name 9 "output"
|
||||||
|
Name 10 "TriStream"
|
||||||
|
Name 20 "@main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1;"
|
||||||
|
Name 18 "input"
|
||||||
|
Name 19 "TriStream"
|
||||||
|
Name 23 "TriStream"
|
||||||
|
Name 27 "param"
|
||||||
|
Name 30 "param"
|
||||||
|
Name 34 "param"
|
||||||
|
Name 37 "param"
|
||||||
|
Name 41 "param"
|
||||||
|
Name 44 "param"
|
||||||
|
Name 47 "input"
|
||||||
|
Name 49 "input"
|
||||||
|
Name 51 "TriStream"
|
||||||
|
Name 52 "param"
|
||||||
|
Name 54 "param"
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6(GSPS_INPUT): TypeStruct
|
||||||
|
7: TypePointer Function 6(GSPS_INPUT)
|
||||||
|
8: TypeFunction 2 7(ptr) 7(ptr)
|
||||||
|
13: TypeInt 32 0
|
||||||
|
14: 13(int) Constant 3
|
||||||
|
15: TypeArray 6(GSPS_INPUT) 14
|
||||||
|
16: TypePointer Function 15
|
||||||
|
17: TypeFunction 2 16(ptr) 7(ptr)
|
||||||
|
22: TypePointer Output 6(GSPS_INPUT)
|
||||||
|
23(TriStream): 22(ptr) Variable Output
|
||||||
|
25: TypeInt 32 1
|
||||||
|
26: 25(int) Constant 0
|
||||||
|
33: 25(int) Constant 1
|
||||||
|
40: 25(int) Constant 2
|
||||||
|
48: TypePointer Input 15
|
||||||
|
49(input): 48(ptr) Variable Input
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
47(input): 16(ptr) Variable Function
|
||||||
|
51(TriStream): 7(ptr) Variable Function
|
||||||
|
52(param): 16(ptr) Variable Function
|
||||||
|
54(param): 7(ptr) Variable Function
|
||||||
|
50: 15 Load 49(input)
|
||||||
|
Store 47(input) 50
|
||||||
|
53: 15 Load 47(input)
|
||||||
|
Store 52(param) 53
|
||||||
|
55: 2 FunctionCall 20(@main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1;) 52(param) 54(param)
|
||||||
|
56:6(GSPS_INPUT) Load 54(param)
|
||||||
|
Store 51(TriStream) 56
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
11(EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1;): 2 Function None 8
|
||||||
|
9(output): 7(ptr) FunctionParameter
|
||||||
|
10(TriStream): 7(ptr) FunctionParameter
|
||||||
|
12: Label
|
||||||
|
24:6(GSPS_INPUT) Load 9(output)
|
||||||
|
Store 23(TriStream) 24
|
||||||
|
EmitVertex
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
|
20(@main(struct-GSPS_INPUT1[3];struct-GSPS_INPUT1;): 2 Function None 17
|
||||||
|
18(input): 16(ptr) FunctionParameter
|
||||||
|
19(TriStream): 7(ptr) FunctionParameter
|
||||||
|
21: Label
|
||||||
|
27(param): 7(ptr) Variable Function
|
||||||
|
30(param): 7(ptr) Variable Function
|
||||||
|
34(param): 7(ptr) Variable Function
|
||||||
|
37(param): 7(ptr) Variable Function
|
||||||
|
41(param): 7(ptr) Variable Function
|
||||||
|
44(param): 7(ptr) Variable Function
|
||||||
|
28: 7(ptr) AccessChain 18(input) 26
|
||||||
|
29:6(GSPS_INPUT) Load 28
|
||||||
|
Store 27(param) 29
|
||||||
|
31: 2 FunctionCall 11(EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1;) 27(param) 30(param)
|
||||||
|
32:6(GSPS_INPUT) Load 30(param)
|
||||||
|
Store 19(TriStream) 32
|
||||||
|
35: 7(ptr) AccessChain 18(input) 33
|
||||||
|
36:6(GSPS_INPUT) Load 35
|
||||||
|
Store 34(param) 36
|
||||||
|
38: 2 FunctionCall 11(EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1;) 34(param) 37(param)
|
||||||
|
39:6(GSPS_INPUT) Load 37(param)
|
||||||
|
Store 19(TriStream) 39
|
||||||
|
42: 7(ptr) AccessChain 18(input) 40
|
||||||
|
43:6(GSPS_INPUT) Load 42
|
||||||
|
Store 41(param) 43
|
||||||
|
45: 2 FunctionCall 11(EmitVertex(struct-GSPS_INPUT1;struct-GSPS_INPUT1;) 41(param) 44(param)
|
||||||
|
46:6(GSPS_INPUT) Load 44(param)
|
||||||
|
Store 19(TriStream) 46
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
||||||
18
Test/hlsl.tristream-append.geom
Normal file
18
Test/hlsl.tristream-append.geom
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
struct GSPS_INPUT
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test Append() method appearing before declaration of entry point's stream output.
|
||||||
|
|
||||||
|
void EmitVertex(in GSPS_INPUT output, inout TriangleStream<GSPS_INPUT> TriStream)
|
||||||
|
{
|
||||||
|
TriStream.Append( output );
|
||||||
|
}
|
||||||
|
|
||||||
|
[maxvertexcount(3)]
|
||||||
|
void main( triangle GSPS_INPUT input[3], inout TriangleStream<GSPS_INPUT> TriStream )
|
||||||
|
{
|
||||||
|
EmitVertex(input[0], TriStream);
|
||||||
|
EmitVertex(input[1], TriStream);
|
||||||
|
EmitVertex(input[2], TriStream);
|
||||||
|
}
|
||||||
|
|
@ -370,6 +370,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||||
{"hlsl.targetStruct1.frag", "main"},
|
{"hlsl.targetStruct1.frag", "main"},
|
||||||
{"hlsl.targetStruct2.frag", "main"},
|
{"hlsl.targetStruct2.frag", "main"},
|
||||||
{"hlsl.templatetypes.frag", "PixelShaderFunction"},
|
{"hlsl.templatetypes.frag", "PixelShaderFunction"},
|
||||||
|
{"hlsl.tristream-append.geom", "main"},
|
||||||
{"hlsl.tx.bracket.frag", "main"},
|
{"hlsl.tx.bracket.frag", "main"},
|
||||||
{"hlsl.tx.overload.frag", "main"},
|
{"hlsl.tx.overload.frag", "main"},
|
||||||
{"hlsl.type.half.frag", "main"},
|
{"hlsl.type.half.frag", "main"},
|
||||||
|
|
|
||||||
|
|
@ -4487,23 +4487,18 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy
|
||||||
emit->setLoc(loc);
|
emit->setLoc(loc);
|
||||||
emit->setType(TType(EbtVoid));
|
emit->setType(TType(EbtVoid));
|
||||||
|
|
||||||
// find the matching output
|
TIntermTyped* data = argAggregate->getSequence()[1]->getAsTyped();
|
||||||
if (gsStreamOutput == nullptr) {
|
|
||||||
error(loc, "unable to find output symbol for Append()", "", "");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence = intermediate.growAggregate(sequence,
|
|
||||||
handleAssign(loc, EOpAssign,
|
|
||||||
intermediate.addSymbol(*gsStreamOutput, loc),
|
|
||||||
argAggregate->getSequence()[1]->getAsTyped()),
|
|
||||||
loc);
|
|
||||||
|
|
||||||
|
// This will be patched in finalization during finalizeAppendMethods()
|
||||||
|
sequence = intermediate.growAggregate(sequence, data, loc);
|
||||||
sequence = intermediate.growAggregate(sequence, emit);
|
sequence = intermediate.growAggregate(sequence, emit);
|
||||||
|
|
||||||
sequence->setOperator(EOpSequence);
|
sequence->setOperator(EOpSequence);
|
||||||
sequence->setLoc(loc);
|
sequence->setLoc(loc);
|
||||||
sequence->setType(TType(EbtVoid));
|
sequence->setType(TType(EbtVoid));
|
||||||
|
|
||||||
|
gsAppends.push_back({sequence, loc});
|
||||||
|
|
||||||
node = sequence;
|
node = sequence;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -9919,6 +9914,31 @@ void HlslParseContext::fixTextureShadowModes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finalization step: patch append methods to use proper stream output, which isn't known until
|
||||||
|
// main is parsed, which could happen after the append method is parsed.
|
||||||
|
void HlslParseContext::finalizeAppendMethods()
|
||||||
|
{
|
||||||
|
TSourceLoc loc;
|
||||||
|
loc.init();
|
||||||
|
|
||||||
|
// Nothing to do: bypass test for valid stream output.
|
||||||
|
if (gsAppends.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gsStreamOutput == nullptr) {
|
||||||
|
error(loc, "unable to find output symbol for Append()", "", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch append sequences, now that we know the stream output symbol.
|
||||||
|
for (auto append = gsAppends.begin(); append != gsAppends.end(); ++append) {
|
||||||
|
append->node->getSequence()[0] =
|
||||||
|
handleAssign(append->loc, EOpAssign,
|
||||||
|
intermediate.addSymbol(*gsStreamOutput, append->loc),
|
||||||
|
append->node->getSequence()[0]->getAsTyped());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// post-processing
|
// post-processing
|
||||||
void HlslParseContext::finish()
|
void HlslParseContext::finish()
|
||||||
{
|
{
|
||||||
|
|
@ -9931,6 +9951,7 @@ void HlslParseContext::finish()
|
||||||
removeUnusedStructBufferCounters();
|
removeUnusedStructBufferCounters();
|
||||||
addPatchConstantInvocation();
|
addPatchConstantInvocation();
|
||||||
fixTextureShadowModes();
|
fixTextureShadowModes();
|
||||||
|
finalizeAppendMethods();
|
||||||
|
|
||||||
// Communicate out (esp. for command line) that we formed AST that will make
|
// Communicate out (esp. for command line) that we formed AST that will make
|
||||||
// illegal AST SPIR-V and it needs transforms to legalize it.
|
// illegal AST SPIR-V and it needs transforms to legalize it.
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,7 @@ protected:
|
||||||
TVariable* getSplitNonIoVar(int id) const;
|
TVariable* getSplitNonIoVar(int id) const;
|
||||||
void addPatchConstantInvocation();
|
void addPatchConstantInvocation();
|
||||||
void fixTextureShadowModes();
|
void fixTextureShadowModes();
|
||||||
|
void finalizeAppendMethods();
|
||||||
TIntermTyped* makeIntegerIndex(TIntermTyped*);
|
TIntermTyped* makeIntegerIndex(TIntermTyped*);
|
||||||
|
|
||||||
void fixBuiltInIoType(TType&);
|
void fixBuiltInIoType(TType&);
|
||||||
|
|
@ -460,6 +461,17 @@ protected:
|
||||||
|
|
||||||
TVector<tMipsOperatorData> mipsOperatorMipArg;
|
TVector<tMipsOperatorData> mipsOperatorMipArg;
|
||||||
|
|
||||||
|
// The geometry output stream is not copied out from the entry point as a typical output variable
|
||||||
|
// is. It's written via EmitVertex (hlsl=Append), which may happen in arbitrary control flow.
|
||||||
|
// For this we need the real output symbol. Since it may not be known at the time and Append()
|
||||||
|
// method is parsed, the sequence will be patched during finalization.
|
||||||
|
struct tGsAppendData {
|
||||||
|
TIntermAggregate* node;
|
||||||
|
TSourceLoc loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
TVector<tGsAppendData> gsAppends;
|
||||||
|
|
||||||
// A texture object may be used with shadow and non-shadow samplers, but both may not be
|
// A texture object may be used with shadow and non-shadow samplers, but both may not be
|
||||||
// alive post-DCE in the same shader. We do not know at compilation time which are alive: that's
|
// alive post-DCE in the same shader. We do not know at compilation time which are alive: that's
|
||||||
// only known post-DCE. If a texture is used both ways, we create two textures, and
|
// only known post-DCE. If a texture is used both ways, we create two textures, and
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue