mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-08 19:40:06 +00:00
Merge pull request #835 from steve-lunarg/sb-counters
HLSL: structuredbuffer counter functionality
This commit is contained in:
commit
a8d3db6b32
223
Test/baseResults/hlsl.structbuffer.append.frag.out
Normal file
223
Test/baseResults/hlsl.structbuffer.append.frag.out
Normal file
@ -0,0 +1,223 @@
|
||||
hlsl.structbuffer.append.frag
|
||||
Shader version: 500
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:7 Function Definition: @main(u1; ( temp 4-component vector of float)
|
||||
0:7 Function Parameters:
|
||||
0:7 'pos' ( in uint)
|
||||
0:? Sequence
|
||||
0:8 move second child to first child ( temp 4-component vector of float)
|
||||
0:8 indirect index (layout( row_major std430) buffer 4-component vector of float)
|
||||
0:8 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
|
||||
0:8 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:8 Constant:
|
||||
0:8 0 (const uint)
|
||||
0:8 AtomicAdd ( temp uint)
|
||||
0:8 @count: direct index for structure ( temp int)
|
||||
0:8 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:8 Constant:
|
||||
0:8 0 (const int)
|
||||
0:8 Constant:
|
||||
0:8 1 (const int)
|
||||
0:? Constant:
|
||||
0:? 1.000000
|
||||
0:? 2.000000
|
||||
0:? 3.000000
|
||||
0:? 4.000000
|
||||
0:10 Branch: Return with expression
|
||||
0:10 indirect index (layout( row_major std430) buffer 4-component vector of float)
|
||||
0:10 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
|
||||
0:10 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:10 Constant:
|
||||
0:10 0 (const uint)
|
||||
0:10 add ( temp uint)
|
||||
0:10 AtomicAdd ( temp uint)
|
||||
0:10 @count: direct index for structure ( temp int)
|
||||
0:10 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:10 Constant:
|
||||
0:10 0 (const int)
|
||||
0:10 Constant:
|
||||
0:10 -1 (const int)
|
||||
0:10 Constant:
|
||||
0:10 -1 (const int)
|
||||
0:7 Function Definition: main( ( temp void)
|
||||
0:7 Function Parameters:
|
||||
0:? Sequence
|
||||
0:7 move second child to first child ( temp uint)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
0:7 move second child to first child ( temp 4-component vector of float)
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:7 Function Call: @main(u1; ( temp 4-component vector of float)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? Linker Objects
|
||||
0:? 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
|
||||
|
||||
Linked fragment stage:
|
||||
|
||||
|
||||
Shader version: 500
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:7 Function Definition: @main(u1; ( temp 4-component vector of float)
|
||||
0:7 Function Parameters:
|
||||
0:7 'pos' ( in uint)
|
||||
0:? Sequence
|
||||
0:8 move second child to first child ( temp 4-component vector of float)
|
||||
0:8 indirect index (layout( row_major std430) buffer 4-component vector of float)
|
||||
0:8 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
|
||||
0:8 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:8 Constant:
|
||||
0:8 0 (const uint)
|
||||
0:8 AtomicAdd ( temp uint)
|
||||
0:8 @count: direct index for structure ( temp int)
|
||||
0:8 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:8 Constant:
|
||||
0:8 0 (const int)
|
||||
0:8 Constant:
|
||||
0:8 1 (const int)
|
||||
0:? Constant:
|
||||
0:? 1.000000
|
||||
0:? 2.000000
|
||||
0:? 3.000000
|
||||
0:? 4.000000
|
||||
0:10 Branch: Return with expression
|
||||
0:10 indirect index (layout( row_major std430) buffer 4-component vector of float)
|
||||
0:10 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
|
||||
0:10 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:10 Constant:
|
||||
0:10 0 (const uint)
|
||||
0:10 add ( temp uint)
|
||||
0:10 AtomicAdd ( temp uint)
|
||||
0:10 @count: direct index for structure ( temp int)
|
||||
0:10 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:10 Constant:
|
||||
0:10 0 (const int)
|
||||
0:10 Constant:
|
||||
0:10 -1 (const int)
|
||||
0:10 Constant:
|
||||
0:10 -1 (const int)
|
||||
0:7 Function Definition: main( ( temp void)
|
||||
0:7 Function Parameters:
|
||||
0:? Sequence
|
||||
0:7 move second child to first child ( temp uint)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
0:7 move second child to first child ( temp 4-component vector of float)
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:7 Function Call: @main(u1; ( temp 4-component vector of float)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? Linker Objects
|
||||
0:? 'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? 'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? 'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 56
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Fragment 4 "main" 48 51
|
||||
ExecutionMode 4 OriginUpperLeft
|
||||
Source HLSL 500
|
||||
Name 4 "main"
|
||||
Name 12 "@main(u1;"
|
||||
Name 11 "pos"
|
||||
Name 15 "sbuf_a"
|
||||
MemberName 15(sbuf_a) 0 "@data"
|
||||
Name 17 "sbuf_a"
|
||||
Name 20 "sbuf_a@count"
|
||||
MemberName 20(sbuf_a@count) 0 "@count"
|
||||
Name 22 "sbuf_a@count"
|
||||
Name 36 "sbuf_c"
|
||||
Name 37 "sbuf_c@count"
|
||||
Name 46 "pos"
|
||||
Name 48 "pos"
|
||||
Name 51 "@entryPointOutput"
|
||||
Name 52 "param"
|
||||
Name 55 "sbuf_unused"
|
||||
Decorate 14 ArrayStride 16
|
||||
MemberDecorate 15(sbuf_a) 0 Offset 0
|
||||
Decorate 15(sbuf_a) BufferBlock
|
||||
Decorate 17(sbuf_a) DescriptorSet 0
|
||||
MemberDecorate 20(sbuf_a@count) 0 Offset 0
|
||||
Decorate 20(sbuf_a@count) BufferBlock
|
||||
Decorate 22(sbuf_a@count) DescriptorSet 0
|
||||
Decorate 36(sbuf_c) DescriptorSet 0
|
||||
Decorate 37(sbuf_c@count) DescriptorSet 0
|
||||
Decorate 48(pos) Location 0
|
||||
Decorate 51(@entryPointOutput) Location 0
|
||||
Decorate 55(sbuf_unused) DescriptorSet 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeInt 32 0
|
||||
7: TypePointer Function 6(int)
|
||||
8: TypeFloat 32
|
||||
9: TypeVector 8(float) 4
|
||||
10: TypeFunction 9(fvec4) 7(ptr)
|
||||
14: TypeRuntimeArray 9(fvec4)
|
||||
15(sbuf_a): TypeStruct 14
|
||||
16: TypePointer Uniform 15(sbuf_a)
|
||||
17(sbuf_a): 16(ptr) Variable Uniform
|
||||
18: TypeInt 32 1
|
||||
19: 18(int) Constant 0
|
||||
20(sbuf_a@count): TypeStruct 18(int)
|
||||
21: TypePointer Uniform 20(sbuf_a@count)
|
||||
22(sbuf_a@count): 21(ptr) Variable Uniform
|
||||
23: TypePointer Uniform 18(int)
|
||||
25: 18(int) Constant 1
|
||||
26: 6(int) Constant 1
|
||||
27: 6(int) Constant 0
|
||||
29: 8(float) Constant 1065353216
|
||||
30: 8(float) Constant 1073741824
|
||||
31: 8(float) Constant 1077936128
|
||||
32: 8(float) Constant 1082130432
|
||||
33: 9(fvec4) ConstantComposite 29 30 31 32
|
||||
34: TypePointer Uniform 9(fvec4)
|
||||
36(sbuf_c): 16(ptr) Variable Uniform
|
||||
37(sbuf_c@count): 21(ptr) Variable Uniform
|
||||
39: 18(int) Constant 4294967295
|
||||
47: TypePointer Input 6(int)
|
||||
48(pos): 47(ptr) Variable Input
|
||||
50: TypePointer Output 9(fvec4)
|
||||
51(@entryPointOutput): 50(ptr) Variable Output
|
||||
55(sbuf_unused): 16(ptr) Variable Uniform
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
46(pos): 7(ptr) Variable Function
|
||||
52(param): 7(ptr) Variable Function
|
||||
49: 6(int) Load 48(pos)
|
||||
Store 46(pos) 49
|
||||
53: 6(int) Load 46(pos)
|
||||
Store 52(param) 53
|
||||
54: 9(fvec4) FunctionCall 12(@main(u1;) 52(param)
|
||||
Store 51(@entryPointOutput) 54
|
||||
Return
|
||||
FunctionEnd
|
||||
12(@main(u1;): 9(fvec4) Function None 10
|
||||
11(pos): 7(ptr) FunctionParameter
|
||||
13: Label
|
||||
24: 23(ptr) AccessChain 22(sbuf_a@count) 19
|
||||
28: 6(int) AtomicIAdd 24 26 27 25
|
||||
35: 34(ptr) AccessChain 17(sbuf_a) 19 28
|
||||
Store 35 33
|
||||
38: 23(ptr) AccessChain 37(sbuf_c@count) 19
|
||||
40: 6(int) AtomicIAdd 38 26 27 39
|
||||
41: 6(int) IAdd 40 39
|
||||
42: 34(ptr) AccessChain 36(sbuf_c) 19 41
|
||||
43: 9(fvec4) Load 42
|
||||
ReturnValue 43
|
||||
FunctionEnd
|
323
Test/baseResults/hlsl.structbuffer.incdec.frag.out
Normal file
323
Test/baseResults/hlsl.structbuffer.incdec.frag.out
Normal file
@ -0,0 +1,323 @@
|
||||
hlsl.structbuffer.incdec.frag
|
||||
Shader version: 500
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:7 Function Definition: @main(u1; ( temp 4-component vector of float)
|
||||
0:7 Function Parameters:
|
||||
0:7 'pos' ( in uint)
|
||||
0:? Sequence
|
||||
0:8 Sequence
|
||||
0:8 move second child to first child ( temp 4-component vector of uint)
|
||||
0:8 'result' ( temp 4-component vector of uint)
|
||||
0:8 Constant:
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:10 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:10 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:10 'sbuf_rw_i' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:10 Constant:
|
||||
0:10 0 (const uint)
|
||||
0:10 Constant:
|
||||
0:10 7 (const int)
|
||||
0:11 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:11 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:11 'sbuf_rw_d' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:11 Constant:
|
||||
0:11 0 (const uint)
|
||||
0:11 Constant:
|
||||
0:11 7 (const int)
|
||||
0:13 move second child to first child ( temp 4-component vector of uint)
|
||||
0:13 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:13 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:13 'sbuf_rw_nocounter' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:13 Constant:
|
||||
0:13 0 (const uint)
|
||||
0:13 Constant:
|
||||
0:13 5 (const int)
|
||||
0:13 Constant:
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:15 Sequence
|
||||
0:15 move second child to first child ( temp uint)
|
||||
0:15 'c1' ( temp uint)
|
||||
0:15 AtomicAdd ( temp uint)
|
||||
0:15 @count: direct index for structure ( temp int)
|
||||
0:15 'sbuf_rw_i@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:15 Constant:
|
||||
0:15 0 (const int)
|
||||
0:15 Constant:
|
||||
0:15 1 (const int)
|
||||
0:16 Sequence
|
||||
0:16 move second child to first child ( temp uint)
|
||||
0:16 'c2' ( temp uint)
|
||||
0:16 add ( temp uint)
|
||||
0:16 AtomicAdd ( temp uint)
|
||||
0:16 @count: direct index for structure ( temp int)
|
||||
0:16 'sbuf_rw_d@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:16 Constant:
|
||||
0:16 0 (const int)
|
||||
0:16 Constant:
|
||||
0:16 -1 (const int)
|
||||
0:16 Constant:
|
||||
0:16 -1 (const int)
|
||||
0:18 Branch: Return with expression
|
||||
0:? Construct vec4 ( temp 4-component vector of float)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 direct index ( temp uint)
|
||||
0:18 'result' ( temp 4-component vector of uint)
|
||||
0:18 Constant:
|
||||
0:18 0 (const int)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 direct index ( temp uint)
|
||||
0:18 'result' ( temp 4-component vector of uint)
|
||||
0:18 Constant:
|
||||
0:18 1 (const int)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 'c1' ( temp uint)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 'c2' ( temp uint)
|
||||
0:7 Function Definition: main( ( temp void)
|
||||
0:7 Function Parameters:
|
||||
0:? Sequence
|
||||
0:7 move second child to first child ( temp uint)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
0:7 move second child to first child ( temp 4-component vector of float)
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:7 Function Call: @main(u1; ( temp 4-component vector of float)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? Linker Objects
|
||||
0:? 'sbuf_rw_i' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? 'sbuf_rw_i@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_rw_d' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? 'sbuf_rw_d@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_rw_nocounter' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
|
||||
|
||||
Linked fragment stage:
|
||||
|
||||
|
||||
Shader version: 500
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:7 Function Definition: @main(u1; ( temp 4-component vector of float)
|
||||
0:7 Function Parameters:
|
||||
0:7 'pos' ( in uint)
|
||||
0:? Sequence
|
||||
0:8 Sequence
|
||||
0:8 move second child to first child ( temp 4-component vector of uint)
|
||||
0:8 'result' ( temp 4-component vector of uint)
|
||||
0:8 Constant:
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:8 0 (const uint)
|
||||
0:10 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:10 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:10 'sbuf_rw_i' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:10 Constant:
|
||||
0:10 0 (const uint)
|
||||
0:10 Constant:
|
||||
0:10 7 (const int)
|
||||
0:11 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:11 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:11 'sbuf_rw_d' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:11 Constant:
|
||||
0:11 0 (const uint)
|
||||
0:11 Constant:
|
||||
0:11 7 (const int)
|
||||
0:13 move second child to first child ( temp 4-component vector of uint)
|
||||
0:13 direct index (layout( row_major std430) buffer 4-component vector of uint)
|
||||
0:13 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint)
|
||||
0:13 'sbuf_rw_nocounter' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:13 Constant:
|
||||
0:13 0 (const uint)
|
||||
0:13 Constant:
|
||||
0:13 5 (const int)
|
||||
0:13 Constant:
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:13 2 (const uint)
|
||||
0:15 Sequence
|
||||
0:15 move second child to first child ( temp uint)
|
||||
0:15 'c1' ( temp uint)
|
||||
0:15 AtomicAdd ( temp uint)
|
||||
0:15 @count: direct index for structure ( temp int)
|
||||
0:15 'sbuf_rw_i@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:15 Constant:
|
||||
0:15 0 (const int)
|
||||
0:15 Constant:
|
||||
0:15 1 (const int)
|
||||
0:16 Sequence
|
||||
0:16 move second child to first child ( temp uint)
|
||||
0:16 'c2' ( temp uint)
|
||||
0:16 add ( temp uint)
|
||||
0:16 AtomicAdd ( temp uint)
|
||||
0:16 @count: direct index for structure ( temp int)
|
||||
0:16 'sbuf_rw_d@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:16 Constant:
|
||||
0:16 0 (const int)
|
||||
0:16 Constant:
|
||||
0:16 -1 (const int)
|
||||
0:16 Constant:
|
||||
0:16 -1 (const int)
|
||||
0:18 Branch: Return with expression
|
||||
0:? Construct vec4 ( temp 4-component vector of float)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 direct index ( temp uint)
|
||||
0:18 'result' ( temp 4-component vector of uint)
|
||||
0:18 Constant:
|
||||
0:18 0 (const int)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 direct index ( temp uint)
|
||||
0:18 'result' ( temp 4-component vector of uint)
|
||||
0:18 Constant:
|
||||
0:18 1 (const int)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 'c1' ( temp uint)
|
||||
0:18 Convert uint to float ( temp float)
|
||||
0:18 'c2' ( temp uint)
|
||||
0:7 Function Definition: main( ( temp void)
|
||||
0:7 Function Parameters:
|
||||
0:? Sequence
|
||||
0:7 move second child to first child ( temp uint)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
0:7 move second child to first child ( temp 4-component vector of float)
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:7 Function Call: @main(u1; ( temp 4-component vector of float)
|
||||
0:? 'pos' ( temp uint)
|
||||
0:? Linker Objects
|
||||
0:? 'sbuf_rw_i' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? 'sbuf_rw_i@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_rw_d' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? 'sbuf_rw_d@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
|
||||
0:? 'sbuf_rw_nocounter' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
|
||||
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
|
||||
0:? 'pos' (layout( location=0) in uint)
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 70
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Fragment 4 "main" 63 66
|
||||
ExecutionMode 4 OriginUpperLeft
|
||||
Source HLSL 500
|
||||
Name 4 "main"
|
||||
Name 12 "@main(u1;"
|
||||
Name 11 "pos"
|
||||
Name 16 "result"
|
||||
Name 20 "sbuf_rw_i"
|
||||
MemberName 20(sbuf_rw_i) 0 "@data"
|
||||
Name 22 "sbuf_rw_i"
|
||||
Name 26 "sbuf_rw_d"
|
||||
Name 27 "sbuf_rw_nocounter"
|
||||
Name 33 "c1"
|
||||
Name 34 "sbuf_rw_i@count"
|
||||
MemberName 34(sbuf_rw_i@count) 0 "@count"
|
||||
Name 36 "sbuf_rw_i@count"
|
||||
Name 42 "c2"
|
||||
Name 43 "sbuf_rw_d@count"
|
||||
Name 61 "pos"
|
||||
Name 63 "pos"
|
||||
Name 66 "@entryPointOutput"
|
||||
Name 67 "param"
|
||||
Decorate 19 ArrayStride 16
|
||||
MemberDecorate 20(sbuf_rw_i) 0 Offset 0
|
||||
Decorate 20(sbuf_rw_i) BufferBlock
|
||||
Decorate 22(sbuf_rw_i) DescriptorSet 0
|
||||
Decorate 26(sbuf_rw_d) DescriptorSet 0
|
||||
Decorate 27(sbuf_rw_nocounter) DescriptorSet 0
|
||||
MemberDecorate 34(sbuf_rw_i@count) 0 Offset 0
|
||||
Decorate 34(sbuf_rw_i@count) BufferBlock
|
||||
Decorate 36(sbuf_rw_i@count) DescriptorSet 0
|
||||
Decorate 43(sbuf_rw_d@count) DescriptorSet 0
|
||||
Decorate 63(pos) Location 0
|
||||
Decorate 66(@entryPointOutput) Location 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeInt 32 0
|
||||
7: TypePointer Function 6(int)
|
||||
8: TypeFloat 32
|
||||
9: TypeVector 8(float) 4
|
||||
10: TypeFunction 9(fvec4) 7(ptr)
|
||||
14: TypeVector 6(int) 4
|
||||
15: TypePointer Function 14(ivec4)
|
||||
17: 6(int) Constant 0
|
||||
18: 14(ivec4) ConstantComposite 17 17 17 17
|
||||
19: TypeRuntimeArray 14(ivec4)
|
||||
20(sbuf_rw_i): TypeStruct 19
|
||||
21: TypePointer Uniform 20(sbuf_rw_i)
|
||||
22(sbuf_rw_i): 21(ptr) Variable Uniform
|
||||
23: TypeInt 32 1
|
||||
24: 23(int) Constant 0
|
||||
25: 23(int) Constant 7
|
||||
26(sbuf_rw_d): 21(ptr) Variable Uniform
|
||||
27(sbuf_rw_nocounter): 21(ptr) Variable Uniform
|
||||
28: 23(int) Constant 5
|
||||
29: 6(int) Constant 2
|
||||
30: 14(ivec4) ConstantComposite 29 29 29 29
|
||||
31: TypePointer Uniform 14(ivec4)
|
||||
34(sbuf_rw_i@count): TypeStruct 23(int)
|
||||
35: TypePointer Uniform 34(sbuf_rw_i@count)
|
||||
36(sbuf_rw_i@count): 35(ptr) Variable Uniform
|
||||
37: TypePointer Uniform 23(int)
|
||||
39: 23(int) Constant 1
|
||||
40: 6(int) Constant 1
|
||||
43(sbuf_rw_d@count): 35(ptr) Variable Uniform
|
||||
45: 23(int) Constant 4294967295
|
||||
62: TypePointer Input 6(int)
|
||||
63(pos): 62(ptr) Variable Input
|
||||
65: TypePointer Output 9(fvec4)
|
||||
66(@entryPointOutput): 65(ptr) Variable Output
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
61(pos): 7(ptr) Variable Function
|
||||
67(param): 7(ptr) Variable Function
|
||||
64: 6(int) Load 63(pos)
|
||||
Store 61(pos) 64
|
||||
68: 6(int) Load 61(pos)
|
||||
Store 67(param) 68
|
||||
69: 9(fvec4) FunctionCall 12(@main(u1;) 67(param)
|
||||
Store 66(@entryPointOutput) 69
|
||||
Return
|
||||
FunctionEnd
|
||||
12(@main(u1;): 9(fvec4) Function None 10
|
||||
11(pos): 7(ptr) FunctionParameter
|
||||
13: Label
|
||||
16(result): 15(ptr) Variable Function
|
||||
33(c1): 7(ptr) Variable Function
|
||||
42(c2): 7(ptr) Variable Function
|
||||
Store 16(result) 18
|
||||
32: 31(ptr) AccessChain 27(sbuf_rw_nocounter) 24 28
|
||||
Store 32 30
|
||||
38: 37(ptr) AccessChain 36(sbuf_rw_i@count) 24
|
||||
41: 6(int) AtomicIAdd 38 40 17 39
|
||||
Store 33(c1) 41
|
||||
44: 37(ptr) AccessChain 43(sbuf_rw_d@count) 24
|
||||
46: 6(int) AtomicIAdd 44 40 17 45
|
||||
47: 6(int) IAdd 46 45
|
||||
Store 42(c2) 47
|
||||
48: 7(ptr) AccessChain 16(result) 17
|
||||
49: 6(int) Load 48
|
||||
50: 8(float) ConvertUToF 49
|
||||
51: 7(ptr) AccessChain 16(result) 40
|
||||
52: 6(int) Load 51
|
||||
53: 8(float) ConvertUToF 52
|
||||
54: 6(int) Load 33(c1)
|
||||
55: 8(float) ConvertUToF 54
|
||||
56: 6(int) Load 42(c2)
|
||||
57: 8(float) ConvertUToF 56
|
||||
58: 9(fvec4) CompositeConstruct 50 53 55 57
|
||||
ReturnValue 58
|
||||
FunctionEnd
|
11
Test/hlsl.structbuffer.append.frag
Normal file
11
Test/hlsl.structbuffer.append.frag
Normal file
@ -0,0 +1,11 @@
|
||||
AppendStructuredBuffer<float4> sbuf_a;
|
||||
ConsumeStructuredBuffer<float4> sbuf_c;
|
||||
|
||||
AppendStructuredBuffer<float4> sbuf_unused;
|
||||
|
||||
float4 main(uint pos : FOO) : SV_Target0
|
||||
{
|
||||
sbuf_a.Append(float4(1,2,3,4));
|
||||
|
||||
return sbuf_c.Consume();
|
||||
}
|
19
Test/hlsl.structbuffer.incdec.frag
Normal file
19
Test/hlsl.structbuffer.incdec.frag
Normal file
@ -0,0 +1,19 @@
|
||||
RWStructuredBuffer<uint4> sbuf_rw_i;
|
||||
RWStructuredBuffer<uint4> sbuf_rw_d;
|
||||
|
||||
RWStructuredBuffer<uint4> sbuf_rw_nocounter; // doesn't use inc or dec
|
||||
|
||||
float4 main(uint pos : FOO) : SV_Target0
|
||||
{
|
||||
uint4 result = 0;
|
||||
|
||||
sbuf_rw_i[7];
|
||||
sbuf_rw_d[7];
|
||||
|
||||
sbuf_rw_nocounter[5] = 2;
|
||||
|
||||
uint c1 = sbuf_rw_i.IncrementCounter();
|
||||
uint c2 = sbuf_rw_d.DecrementCounter();
|
||||
|
||||
return float4(result.x, result.y, c1, c2);
|
||||
}
|
@ -223,6 +223,13 @@ enum TBuiltInVariable {
|
||||
EbvOutputPatch,
|
||||
EbvInputPatch,
|
||||
|
||||
// structbuffer types
|
||||
EbvAppendConsume, // no need to differentiate append and consume
|
||||
EbvRWStructuredBuffer,
|
||||
EbvStructuredBuffer,
|
||||
EbvByteAddressBuffer,
|
||||
EbvRWByteAddressBuffer,
|
||||
|
||||
EbvLast
|
||||
};
|
||||
|
||||
|
@ -633,6 +633,10 @@ enum TOperator {
|
||||
EOpMethodStore2, // ...
|
||||
EOpMethodStore3, // ...
|
||||
EOpMethodStore4, // ...
|
||||
EOpMethodIncrementCounter, // ...
|
||||
EOpMethodDecrementCounter, // ...
|
||||
// EOpMethodAppend is defined for geo shaders below
|
||||
EOpMethodConsume,
|
||||
|
||||
// SM5 texture methods
|
||||
EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about
|
||||
|
@ -1778,6 +1778,7 @@ const char* TProgram::getUniformBlockName(int index) const { return reflection
|
||||
int TProgram::getUniformBlockSize(int index) const { return reflection->getUniformBlock(index).size; }
|
||||
int TProgram::getUniformIndex(const char* name) const { return reflection->getIndex(name); }
|
||||
int TProgram::getUniformBlockIndex(int index) const { return reflection->getUniform(index).index; }
|
||||
int TProgram::getUniformBlockCounterIndex(int index) const { return reflection->getUniformBlock(index).counterIndex; }
|
||||
int TProgram::getUniformType(int index) const { return reflection->getUniform(index).glDefineType; }
|
||||
int TProgram::getUniformBufferOffset(int index) const { return reflection->getUniform(index).offset; }
|
||||
int TProgram::getUniformArraySize(int index) const { return reflection->getUniform(index).size; }
|
||||
|
@ -707,6 +707,19 @@ void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediat
|
||||
}
|
||||
}
|
||||
|
||||
// build counter block index associations for buffers
|
||||
void TReflection::buildCounterIndices()
|
||||
{
|
||||
// search for ones that have counters
|
||||
for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
|
||||
const TString counterName(indexToUniformBlock[i].name + "@count");
|
||||
const int index = getIndex(counterName);
|
||||
|
||||
if (index >= 0)
|
||||
indexToUniformBlock[i].counterIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge live symbols from 'intermediate' into the existing reflection database.
|
||||
//
|
||||
// Returns false if the input is too malformed to do this.
|
||||
@ -729,6 +742,8 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
|
||||
function->traverse(&it);
|
||||
}
|
||||
|
||||
buildCounterIndices();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,16 @@ class TObjectReflection {
|
||||
public:
|
||||
TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
|
||||
name(pName), offset(pOffset),
|
||||
glDefineType(pGLDefineType), size(pSize), index(pIndex), type(pType.clone()) { }
|
||||
glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { }
|
||||
|
||||
void dump() const {
|
||||
printf("%s: offset %d, type %x, size %d, index %d, binding %d\n",
|
||||
printf("%s: offset %d, type %x, size %d, index %d, binding %d",
|
||||
name.c_str(), offset, glDefineType, size, index, getBinding() );
|
||||
|
||||
if (counterIndex != -1)
|
||||
printf(", counter %d", counterIndex);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
const TType* const getType() const { return type; }
|
||||
@ -71,6 +76,7 @@ public:
|
||||
int glDefineType;
|
||||
int size; // data size in bytes for a block, array size for a (non-block) object that's an array
|
||||
int index;
|
||||
int counterIndex;
|
||||
|
||||
static TObjectReflection badReflection() { return TObjectReflection(); }
|
||||
|
||||
@ -140,6 +146,9 @@ public:
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// see getIndex(const char*)
|
||||
int getIndex(const TString& name) const { return getIndex(name.c_str()); }
|
||||
|
||||
// Thread local size
|
||||
unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
|
||||
|
||||
@ -148,6 +157,7 @@ public:
|
||||
protected:
|
||||
friend class glslang::TReflectionTraverser;
|
||||
|
||||
void buildCounterIndices();
|
||||
void buildAttributeReflection(EShLanguage, const TIntermediate&);
|
||||
|
||||
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
|
||||
|
@ -518,6 +518,7 @@ public:
|
||||
int getUniformBlockSize(int blockIndex) const; // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
|
||||
int getUniformIndex(const char* name) const; // can be used for glGetUniformIndices()
|
||||
int getUniformBlockIndex(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
|
||||
int getUniformBlockCounterIndex(int index) const; // returns block index of associated counter.
|
||||
int getUniformType(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
|
||||
int getUniformBufferOffset(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
|
||||
int getUniformArraySize(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
|
||||
|
@ -245,9 +245,11 @@ INSTANTIATE_TEST_CASE_P(
|
||||
{"hlsl.structarray.flatten.frag", "main"},
|
||||
{"hlsl.structarray.flatten.geom", "main"},
|
||||
{"hlsl.structbuffer.frag", "main"},
|
||||
{"hlsl.structbuffer.append.frag", "main"},
|
||||
{"hlsl.structbuffer.atomics.frag", "main"},
|
||||
{"hlsl.structbuffer.byte.frag", "main"},
|
||||
{"hlsl.structbuffer.coherent.frag", "main"},
|
||||
{"hlsl.structbuffer.incdec.frag", "main"},
|
||||
{"hlsl.structbuffer.fn.frag", "main"},
|
||||
{"hlsl.structbuffer.rw.frag", "main"},
|
||||
{"hlsl.structbuffer.rwbyte.frag", "main"},
|
||||
|
@ -475,9 +475,10 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
||||
if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
|
||||
if (typedefDecl)
|
||||
parseContext.declareTypedef(idToken.loc, *fullName, variableType);
|
||||
else if (variableType.getBasicType() == EbtBlock)
|
||||
else if (variableType.getBasicType() == EbtBlock) {
|
||||
parseContext.declareBlock(idToken.loc, variableType, fullName);
|
||||
else {
|
||||
parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
|
||||
} else {
|
||||
if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
|
||||
// this isn't really an individual variable, but a member of the $Global buffer
|
||||
parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
|
||||
@ -1955,24 +1956,29 @@ bool HlslGrammar::acceptStructBufferType(TType& type)
|
||||
bool readonly = false;
|
||||
|
||||
TStorageQualifier storage = EvqBuffer;
|
||||
TBuiltInVariable builtinType = EbvNone;
|
||||
|
||||
switch (structBuffType) {
|
||||
case EHTokAppendStructuredBuffer:
|
||||
unimplemented("AppendStructuredBuffer");
|
||||
return false;
|
||||
builtinType = EbvAppendConsume;
|
||||
break;
|
||||
case EHTokByteAddressBuffer:
|
||||
hasTemplateType = false;
|
||||
readonly = true;
|
||||
builtinType = EbvByteAddressBuffer;
|
||||
break;
|
||||
case EHTokConsumeStructuredBuffer:
|
||||
unimplemented("ConsumeStructuredBuffer");
|
||||
return false;
|
||||
builtinType = EbvAppendConsume;
|
||||
break;
|
||||
case EHTokRWByteAddressBuffer:
|
||||
hasTemplateType = false;
|
||||
builtinType = EbvRWByteAddressBuffer;
|
||||
break;
|
||||
case EHTokRWStructuredBuffer:
|
||||
builtinType = EbvRWStructuredBuffer;
|
||||
break;
|
||||
case EHTokStructuredBuffer:
|
||||
builtinType = EbvStructuredBuffer;
|
||||
readonly = true;
|
||||
break;
|
||||
default:
|
||||
@ -2014,8 +2020,6 @@ bool HlslGrammar::acceptStructBufferType(TType& type)
|
||||
// field name is canonical for all structbuffers
|
||||
templateType->setFieldName("@data");
|
||||
|
||||
// Create block type. TODO: hidden internal uint member when needed
|
||||
|
||||
TTypeList* blockStruct = new TTypeList;
|
||||
TTypeLoc member = { templateType, token.loc };
|
||||
blockStruct->push_back(member);
|
||||
@ -2025,6 +2029,7 @@ bool HlslGrammar::acceptStructBufferType(TType& type)
|
||||
|
||||
blockType.getQualifier().storage = storage;
|
||||
blockType.getQualifier().readonly = readonly;
|
||||
blockType.getQualifier().builtIn = builtinType;
|
||||
|
||||
// We may have created an equivalent type before, in which case we should use its
|
||||
// deep structure.
|
||||
|
@ -842,7 +842,11 @@ bool HlslParseContext::isStructBufferMethod(const TString& name) const
|
||||
name == "InterlockedMax" ||
|
||||
name == "InterlockedMin" ||
|
||||
name == "InterlockedOr" ||
|
||||
name == "InterlockedXor";
|
||||
name == "InterlockedXor" ||
|
||||
name == "IncrementCounter" ||
|
||||
name == "DecrementCounter" ||
|
||||
name == "Append" ||
|
||||
name == "Consume";
|
||||
}
|
||||
|
||||
//
|
||||
@ -1514,7 +1518,7 @@ void HlslParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction
|
||||
error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
|
||||
}
|
||||
|
||||
// Add interstage IO variables to the linkage in canonical order.
|
||||
// Finalization step: Add interstage IO variables to the linkage in canonical order.
|
||||
void HlslParseContext::addInterstageIoToLinkage()
|
||||
{
|
||||
TSourceLoc loc;
|
||||
@ -2438,24 +2442,125 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc
|
||||
return txcombine;
|
||||
}
|
||||
|
||||
// Return true if this a buffer type that has an associated counter buffer.
|
||||
bool HlslParseContext::hasStructBuffCounter(const TString& name) const
|
||||
{
|
||||
const auto bivIt = structBufferBuiltIn.find(name);
|
||||
if (bivIt == structBufferBuiltIn.end())
|
||||
return false;
|
||||
|
||||
switch (bivIt->second) {
|
||||
case EbvAppendConsume: // fall through...
|
||||
case EbvRWStructuredBuffer: // ...
|
||||
return true;
|
||||
default:
|
||||
return false; // the other structuredbfufer types do not have a counter.
|
||||
}
|
||||
}
|
||||
|
||||
// declare counter for a structured buffer type
|
||||
void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name)
|
||||
{
|
||||
// Bail out if not a struct buffer
|
||||
if (! isStructBufferType(bufferType))
|
||||
return;
|
||||
|
||||
if (! hasStructBuffCounter(name))
|
||||
return;
|
||||
|
||||
// Counter type
|
||||
TType* counterType = new TType(EbtInt, EvqBuffer);
|
||||
counterType->setFieldName("@count");
|
||||
|
||||
TTypeList* blockStruct = new TTypeList;
|
||||
TTypeLoc member = { counterType, loc };
|
||||
blockStruct->push_back(member);
|
||||
|
||||
TString* blockName = new TString(name);
|
||||
*blockName += "@count";
|
||||
|
||||
structBufferCounter[*blockName] = false;
|
||||
|
||||
TType blockType(blockStruct, "", counterType->getQualifier());
|
||||
blockType.getQualifier().storage = EvqBuffer;
|
||||
|
||||
shareStructBufferType(blockType);
|
||||
declareBlock(loc, blockType, blockName);
|
||||
}
|
||||
|
||||
// return the counter that goes with a given structuredbuffer
|
||||
TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer)
|
||||
{
|
||||
// Bail out if not a struct buffer
|
||||
if (buffer == nullptr || ! isStructBufferType(buffer->getType()))
|
||||
return nullptr;
|
||||
|
||||
TString blockName(buffer->getAsSymbolNode()->getName());
|
||||
blockName += "@count";
|
||||
|
||||
// Mark the counter as being used
|
||||
structBufferCounter[blockName] = true;
|
||||
|
||||
TIntermTyped* counterVar = handleVariable(loc, &blockName); // find the block structure
|
||||
TIntermTyped* index = intermediate.addConstantUnion(0, loc); // index to counter inside block struct
|
||||
|
||||
TIntermTyped* counterMember = intermediate.addIndex(EOpIndexDirectStruct, counterVar, index, loc);
|
||||
counterMember->setType(TType(EbtInt));
|
||||
return counterMember;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Decompose structure buffer methods into AST
|
||||
//
|
||||
void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments)
|
||||
{
|
||||
if (!node || !node->getAsOperator())
|
||||
if (node == nullptr || node->getAsOperator() == nullptr || arguments == nullptr)
|
||||
return;
|
||||
|
||||
const TOperator op = node->getAsOperator()->getOp();
|
||||
TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr;
|
||||
if (argAggregate == nullptr)
|
||||
return;
|
||||
|
||||
if (argAggregate->getSequence().empty())
|
||||
return;
|
||||
TIntermAggregate* argAggregate = arguments->getAsAggregate();
|
||||
|
||||
// Buffer is the object upon which method is called, so always arg 0
|
||||
TIntermTyped* bufferObj = argAggregate->getSequence()[0]->getAsTyped();
|
||||
TIntermTyped* bufferObj = nullptr;
|
||||
|
||||
// The parameters can be an aggregate, or just a the object as a symbol if there are no fn params.
|
||||
if (argAggregate) {
|
||||
if (argAggregate->getSequence().empty())
|
||||
return;
|
||||
bufferObj = argAggregate->getSequence()[0]->getAsTyped();
|
||||
} else {
|
||||
bufferObj = arguments->getAsSymbolNode();
|
||||
}
|
||||
|
||||
if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr)
|
||||
return;
|
||||
|
||||
TString bufferName(bufferObj->getAsSymbolNode()->getName());
|
||||
|
||||
const auto bivIt = structBufferBuiltIn.find(bufferName);
|
||||
if (bivIt == structBufferBuiltIn.end())
|
||||
return;
|
||||
|
||||
const TBuiltInVariable builtInType = bivIt->second;
|
||||
|
||||
// Some methods require a hidden internal counter, obtained via getStructBufferCounter().
|
||||
// This lambda adds something to it and returns the old value.
|
||||
const auto incDecCounter = [&](int incval) -> TIntermTyped* {
|
||||
TIntermTyped* incrementValue = intermediate.addConstantUnion(incval, loc, true);
|
||||
TIntermTyped* counter = getStructBufferCounter(loc, bufferObj); // obtain the counter member
|
||||
|
||||
if (counter == nullptr)
|
||||
return nullptr;
|
||||
|
||||
TIntermAggregate* counterIncrement = new TIntermAggregate(EOpAtomicAdd);
|
||||
counterIncrement->setType(TType(EbtUint, EvqTemporary));
|
||||
counterIncrement->setLoc(loc);
|
||||
counterIncrement->getSequence().push_back(counter);
|
||||
counterIncrement->getSequence().push_back(incrementValue);
|
||||
|
||||
return counterIncrement;
|
||||
};
|
||||
|
||||
// Index to obtain the runtime sized array out of the buffer.
|
||||
TIntermTyped* argArray = indexStructBufferContent(loc, bufferObj);
|
||||
@ -2469,7 +2574,9 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
|
||||
|
||||
// Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address
|
||||
// buffer then, but that's what it calls itself.
|
||||
const bool isByteAddressBuffer = (argArray->getBasicType() == EbtUint);
|
||||
const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer ||
|
||||
builtInType == EbvRWByteAddressBuffer);
|
||||
|
||||
if (isByteAddressBuffer)
|
||||
argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, intermediate.addConstantUnion(2, loc, true),
|
||||
loc, TType(EbtInt));
|
||||
@ -2670,6 +2777,50 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
|
||||
}
|
||||
break;
|
||||
|
||||
case EOpMethodIncrementCounter:
|
||||
{
|
||||
node = incDecCounter(1);
|
||||
break;
|
||||
}
|
||||
|
||||
case EOpMethodDecrementCounter:
|
||||
{
|
||||
TIntermTyped* preIncValue = incDecCounter(-1); // result is original value
|
||||
node = intermediate.addBinaryNode(EOpAdd, preIncValue, intermediate.addConstantUnion(-1, loc, true), loc,
|
||||
preIncValue->getType());
|
||||
break;
|
||||
}
|
||||
|
||||
case EOpMethodAppend:
|
||||
{
|
||||
TIntermTyped* oldCounter = incDecCounter(1);
|
||||
|
||||
TIntermTyped* lValue = intermediate.addIndex(EOpIndexIndirect, argArray, oldCounter, loc);
|
||||
TIntermTyped* rValue = argAggregate->getSequence()[1]->getAsTyped();
|
||||
|
||||
const TType derefType(argArray->getType(), 0);
|
||||
lValue->setType(derefType);
|
||||
|
||||
node = intermediate.addAssign(EOpAssign, lValue, rValue, loc);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EOpMethodConsume:
|
||||
{
|
||||
TIntermTyped* oldCounter = incDecCounter(-1);
|
||||
|
||||
TIntermTyped* newCounter = intermediate.addBinaryNode(EOpAdd, oldCounter, intermediate.addConstantUnion(-1, loc, true), loc,
|
||||
oldCounter->getType());
|
||||
|
||||
node = intermediate.addIndex(EOpIndexIndirect, argArray, newCounter, loc);
|
||||
|
||||
const TType derefType(argArray->getType(), 0);
|
||||
node->setType(derefType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break; // most pass through unchanged
|
||||
}
|
||||
@ -3978,10 +4129,18 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
|
||||
// TODO: this needs improvement: there's no way at present to look up a signature in
|
||||
// the symbol table for an arbitrary type. This is a temporary hack until that ability exists.
|
||||
// It will have false positives, since it doesn't check arg counts or types.
|
||||
if (arguments && arguments->getAsAggregate()) {
|
||||
const TIntermSequence& sequence = arguments->getAsAggregate()->getSequence();
|
||||
if (arguments) {
|
||||
// Check if first argument is struct buffer type. It may be an aggregate or a symbol, so we
|
||||
// look for either case.
|
||||
|
||||
if (!sequence.empty() && isStructBufferType(sequence[0]->getAsTyped()->getType())) {
|
||||
TIntermTyped* arg0 = nullptr;
|
||||
|
||||
if (arguments->getAsAggregate() && arguments->getAsAggregate()->getSequence().size() > 0)
|
||||
arg0 = arguments->getAsAggregate()->getSequence()[0]->getAsTyped();
|
||||
else if (arguments->getAsSymbolNode())
|
||||
arg0 = arguments->getAsSymbolNode();
|
||||
|
||||
if (arg0 != nullptr && isStructBufferType(arg0->getType())) {
|
||||
static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1;
|
||||
|
||||
if (function->getName().length() > methodPrefixSize &&
|
||||
@ -5845,8 +6004,11 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
|
||||
// These builtin ops can accept any type, so we bypass the argument selection
|
||||
if (candidateList.size() == 1 && builtIn &&
|
||||
(candidateList[0]->getBuiltInOp() == EOpMethodAppend ||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip)) {
|
||||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip ||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodIncrementCounter ||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodDecrementCounter ||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodAppend ||
|
||||
candidateList[0]->getBuiltInOp() == EOpMethodConsume)) {
|
||||
return candidateList[0];
|
||||
}
|
||||
|
||||
@ -6856,6 +7018,10 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS
|
||||
switch (type.getQualifier().storage) {
|
||||
case EvqUniform:
|
||||
case EvqBuffer:
|
||||
// remember pre-sanitized builtin type
|
||||
if (type.getQualifier().storage == EvqBuffer && instanceName != nullptr)
|
||||
structBufferBuiltIn[*instanceName] = type.getQualifier().builtIn;
|
||||
|
||||
correctUniform(type.getQualifier());
|
||||
break;
|
||||
case EvqVaryingIn:
|
||||
@ -7670,7 +7836,7 @@ TIntermSymbol* HlslParseContext::findLinkageSymbol(TBuiltInVariable biType) cons
|
||||
return intermediate.addSymbol(*it->second->getAsVariable());
|
||||
}
|
||||
|
||||
// Add patch constant function invocation
|
||||
// Finalization step: Add patch constant function invocation
|
||||
void HlslParseContext::addPatchConstantInvocation()
|
||||
{
|
||||
TSourceLoc loc;
|
||||
@ -8039,9 +8205,23 @@ void HlslParseContext::addPatchConstantInvocation()
|
||||
epBodySeq.insert(epBodySeq.end(), invocationIdTest);
|
||||
}
|
||||
|
||||
// Finalization step: remove unused buffer blocks from linkage (we don't know until the
|
||||
// shader is entirely compiled)
|
||||
void HlslParseContext::removeUnusedStructBufferCounters()
|
||||
{
|
||||
const auto endIt = std::remove_if(linkageSymbols.begin(), linkageSymbols.end(),
|
||||
[this](const TSymbol* sym) {
|
||||
const auto sbcIt = structBufferCounter.find(sym->getName());
|
||||
return sbcIt != structBufferCounter.end() && !sbcIt->second;
|
||||
});
|
||||
|
||||
linkageSymbols.erase(endIt, linkageSymbols.end());
|
||||
}
|
||||
|
||||
// post-processing
|
||||
void HlslParseContext::finish()
|
||||
{
|
||||
removeUnusedStructBufferCounters();
|
||||
addPatchConstantInvocation();
|
||||
addInterstageIoToLinkage();
|
||||
|
||||
|
@ -146,6 +146,7 @@ public:
|
||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
||||
void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name);
|
||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
||||
void fixBlockXfbOffsets(TQualifier&, TTypeList&);
|
||||
void fixBlockUniformOffsets(const TQualifier&, TTypeList&);
|
||||
@ -274,11 +275,19 @@ protected:
|
||||
TType* getStructBufferContentType(const TType& type) const;
|
||||
bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; }
|
||||
TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const;
|
||||
TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer);
|
||||
|
||||
// Return true if this type is a reference. This is not currently a type method in case that's
|
||||
// a language specific answer.
|
||||
bool isReference(const TType& type) const { return isStructBufferType(type); }
|
||||
|
||||
// Return true if this a buffer type that has an associated counter buffer.
|
||||
bool hasStructBuffCounter(const TString& name) const;
|
||||
|
||||
// Finalization step: remove unused buffer blocks from linkage (we don't know until the
|
||||
// shader is entirely compiled)
|
||||
void removeUnusedStructBufferCounters();
|
||||
|
||||
// Pass through to base class after remembering builtin mappings.
|
||||
using TParseContextBase::trackLinkage;
|
||||
void trackLinkage(TSymbol& variable) override;
|
||||
@ -367,6 +376,9 @@ protected:
|
||||
// Structuredbuffer shared types. Typically there are only a few.
|
||||
TVector<TType*> structBufferTypes;
|
||||
|
||||
TMap<TString, TBuiltInVariable> structBufferBuiltIn;
|
||||
TMap<TString, bool> structBufferCounter;
|
||||
|
||||
// The builtin interstage IO map considers e.g, EvqPosition on input and output separately, so that we
|
||||
// can build the linkage correctly if position appears on both sides. Otherwise, multiple positions
|
||||
// are considered identical.
|
||||
|
@ -871,6 +871,9 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
|
||||
{ "InterlockedMin", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
{ "InterlockedOr", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
{ "InterlockedXor", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
{ "IncrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
{ "DecrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
{ "Consume", nullptr, nullptr, "-", "-", EShLangAll, true },
|
||||
|
||||
// Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet.
|
||||
{ nullptr, nullptr, nullptr, nullptr, nullptr, 0, false },
|
||||
@ -1180,6 +1183,10 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "Store2", EOpMethodStore2);
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "Store3", EOpMethodStore3);
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "Store4", EOpMethodStore4);
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "IncrementCounter", EOpMethodIncrementCounter);
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "DecrementCounter", EOpMethodDecrementCounter);
|
||||
// Append is also a GS method: we don't add it twice
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "Consume", EOpMethodConsume);
|
||||
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAdd", EOpInterlockedAdd);
|
||||
symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAnd", EOpInterlockedAnd);
|
||||
|
Loading…
Reference in New Issue
Block a user