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
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.targetStruct2.frag", "main"},
|
||||
{"hlsl.templatetypes.frag", "PixelShaderFunction"},
|
||||
{"hlsl.tristream-append.geom", "main"},
|
||||
{"hlsl.tx.bracket.frag", "main"},
|
||||
{"hlsl.tx.overload.frag", "main"},
|
||||
{"hlsl.type.half.frag", "main"},
|
||||
|
||||
@ -4487,23 +4487,18 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy
|
||||
emit->setLoc(loc);
|
||||
emit->setType(TType(EbtVoid));
|
||||
|
||||
// find the matching output
|
||||
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);
|
||||
TIntermTyped* data = argAggregate->getSequence()[1]->getAsTyped();
|
||||
|
||||
// This will be patched in finalization during finalizeAppendMethods()
|
||||
sequence = intermediate.growAggregate(sequence, data, loc);
|
||||
sequence = intermediate.growAggregate(sequence, emit);
|
||||
|
||||
sequence->setOperator(EOpSequence);
|
||||
sequence->setLoc(loc);
|
||||
sequence->setType(TType(EbtVoid));
|
||||
|
||||
gsAppends.push_back({sequence, loc});
|
||||
|
||||
node = sequence;
|
||||
}
|
||||
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
|
||||
void HlslParseContext::finish()
|
||||
{
|
||||
@ -9931,6 +9951,7 @@ void HlslParseContext::finish()
|
||||
removeUnusedStructBufferCounters();
|
||||
addPatchConstantInvocation();
|
||||
fixTextureShadowModes();
|
||||
finalizeAppendMethods();
|
||||
|
||||
// Communicate out (esp. for command line) that we formed AST that will make
|
||||
// illegal AST SPIR-V and it needs transforms to legalize it.
|
||||
|
||||
@ -266,6 +266,7 @@ protected:
|
||||
TVariable* getSplitNonIoVar(int id) const;
|
||||
void addPatchConstantInvocation();
|
||||
void fixTextureShadowModes();
|
||||
void finalizeAppendMethods();
|
||||
TIntermTyped* makeIntegerIndex(TIntermTyped*);
|
||||
|
||||
void fixBuiltInIoType(TType&);
|
||||
@ -460,6 +461,17 @@ protected:
|
||||
|
||||
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
|
||||
// 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user