Commit 80829fed by Neil Henning

Very WIP wave ops.

parent 3cf27e00
This source diff could not be displayed because it is too large. You can view the blob instead.
hlsl.waveordered.comp
Shader version: 500
local_size = (32, 16, 1)
0:? Sequence
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 move second child to first child ( temp uint)
0:6 indirect index (layout( row_major std430) buffer uint)
0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:6 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:6 Constant:
0:6 0 (const uint)
0:6 add ( temp uint)
0:6 add ( temp uint)
0:6 component-wise multiply ( temp uint)
0:6 add ( temp uint)
0:6 component-wise multiply ( temp uint)
0:6 direct index ( temp uint)
0:6 '@gl_NumWorkGroups' ( in 3-component vector of uint NumWorkGroups)
0:6 Constant:
0:6 1 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 2 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 1 (const int)
0:6 component-wise multiply ( temp uint)
0:6 '@gl_NumSubgroups' ( in uint unknown built-in variable)
0:6 direct index ( temp uint)
0:6 '@gl_NumWorkGroups' ( in 3-component vector of uint NumWorkGroups)
0:6 Constant:
0:6 0 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 0 (const int)
0:6 '@gl_SubgroupID' ( in uint unknown built-in variable)
0:6 Constant:
0:6 1 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
Linked compute stage:
Shader version: 500
local_size = (32, 16, 1)
0:? Sequence
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 move second child to first child ( temp uint)
0:6 indirect index (layout( row_major std430) buffer uint)
0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:6 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:6 Constant:
0:6 0 (const uint)
0:6 add ( temp uint)
0:6 add ( temp uint)
0:6 component-wise multiply ( temp uint)
0:6 add ( temp uint)
0:6 component-wise multiply ( temp uint)
0:6 direct index ( temp uint)
0:6 '@gl_NumWorkGroups' ( in 3-component vector of uint NumWorkGroups)
0:6 Constant:
0:6 1 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 2 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 1 (const int)
0:6 component-wise multiply ( temp uint)
0:6 '@gl_NumSubgroups' ( in uint unknown built-in variable)
0:6 direct index ( temp uint)
0:6 '@gl_NumWorkGroups' ( in 3-component vector of uint NumWorkGroups)
0:6 Constant:
0:6 0 (const int)
0:6 direct index ( temp uint)
0:6 '@gl_WorkGroupID' ( in 3-component vector of uint WorkGroupID)
0:6 Constant:
0:6 0 (const int)
0:6 '@gl_SubgroupID' ( in uint unknown built-in variable)
0:6 Constant:
0:6 1 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 46
Capability Shader
Capability GroupNonUniform
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "CSMain" 17 22 30 40
ExecutionMode 4 LocalSize 32 16 1
Source HLSL 500
Name 4 "CSMain"
Name 6 "@CSMain("
Name 10 "data"
MemberName 10(data) 0 "@data"
Name 12 "data"
Name 17 "@gl_NumWorkGroups"
Name 22 "@gl_WorkGroupID"
Name 30 "@gl_NumSubgroups"
Name 40 "@gl_SubgroupID"
Decorate 9 ArrayStride 4
MemberDecorate 10(data) 0 Offset 0
Decorate 10(data) BufferBlock
Decorate 12(data) DescriptorSet 0
Decorate 17(@gl_NumWorkGroups) BuiltIn NumWorkgroups
Decorate 22(@gl_WorkGroupID) BuiltIn WorkgroupId
Decorate 30(@gl_NumSubgroups) BuiltIn NumSubgroups
Decorate 40(@gl_SubgroupID) BuiltIn SubgroupId
2: TypeVoid
3: TypeFunction 2
8: TypeInt 32 0
9: TypeRuntimeArray 8(int)
10(data): TypeStruct 9
11: TypePointer Uniform 10(data)
12(data): 11(ptr) Variable Uniform
13: TypeInt 32 1
14: 13(int) Constant 0
15: TypeVector 8(int) 3
16: TypePointer Input 15(ivec3)
17(@gl_NumWorkGroups): 16(ptr) Variable Input
18: 8(int) Constant 1
19: TypePointer Input 8(int)
22(@gl_WorkGroupID): 16(ptr) Variable Input
23: 8(int) Constant 2
30(@gl_NumSubgroups): 19(ptr) Variable Input
32: 8(int) Constant 0
40(@gl_SubgroupID): 19(ptr) Variable Input
43: TypePointer Uniform 8(int)
4(CSMain): 2 Function None 3
5: Label
45: 2 FunctionCall 6(@CSMain()
Return
FunctionEnd
6(@CSMain(): 2 Function None 3
7: Label
20: 19(ptr) AccessChain 17(@gl_NumWorkGroups) 18
21: 8(int) Load 20
24: 19(ptr) AccessChain 22(@gl_WorkGroupID) 23
25: 8(int) Load 24
26: 8(int) IMul 21 25
27: 19(ptr) AccessChain 22(@gl_WorkGroupID) 18
28: 8(int) Load 27
29: 8(int) IAdd 26 28
31: 8(int) Load 30(@gl_NumSubgroups)
33: 19(ptr) AccessChain 17(@gl_NumWorkGroups) 32
34: 8(int) Load 33
35: 8(int) IMul 31 34
36: 8(int) IMul 29 35
37: 19(ptr) AccessChain 22(@gl_WorkGroupID) 32
38: 8(int) Load 37
39: 8(int) IAdd 36 38
41: 8(int) Load 40(@gl_SubgroupID)
42: 8(int) IAdd 39 41
44: 43(ptr) AccessChain 12(data) 14 42
Store 44 18
Return
FunctionEnd
hlsl.waveordered.frag
ERROR: 0:3: 'WaveGetOrderedIndex' : WaveGetOrderedIndex() unsupported in a pixel/fragment shader
ERROR: 1 compilation errors. No code generated.
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Test condition and select ( temp void)
0:3 Condition
0:3 Compare Equal ( temp bool)
0:3 Constant:
0:3 0 (const uint)
0:3 ERROR: Bad aggregation op
( temp uint)
0:3 true case
0:? Sequence
0:5 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:3 false case
0:? Sequence
0:9 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( 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
ERROR: node is still EOpNull!
0:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Test condition and select ( temp void)
0:3 Condition
0:3 Compare Equal ( temp bool)
0:3 Constant:
0:3 0 (const uint)
0:3 ERROR: Bad aggregation op
( temp uint)
0:3 true case
0:? Sequence
0:5 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:3 false case
0:? Sequence
0:9 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( temp 4-component vector of float)
0:? Linker Objects
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
SPIR-V is not generated for failed compile or link
hlsl.waveordered2.comp
ERROR: 0:7: 'GlobalOrderedCountIncrement' : GlobalOrderedCountIncrement() unsupported
ERROR: 1 compilation errors. No code generated.
Shader version: 500
local_size = (32, 16, 1)
ERROR: node is still EOpNull!
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 Sequence
0:6 move second child to first child ( temp uint)
0:6 'i' ( temp uint)
0:6 Constant:
0:6 42 (const uint)
0:7 move second child to first child ( temp uint)
0:7 indirect index (layout( row_major std430) buffer uint)
0:7 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:7 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:7 Constant:
0:7 0 (const uint)
0:7 ERROR: Bad unary op
( temp uint)
0:7 'i' ( temp uint)
0:7 Constant:
0:7 1 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
Linked compute stage:
Shader version: 500
local_size = (32, 16, 1)
ERROR: node is still EOpNull!
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 Sequence
0:6 move second child to first child ( temp uint)
0:6 'i' ( temp uint)
0:6 Constant:
0:6 42 (const uint)
0:7 move second child to first child ( temp uint)
0:7 indirect index (layout( row_major std430) buffer uint)
0:7 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:7 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:7 Constant:
0:7 0 (const uint)
0:7 ERROR: Bad unary op
( temp uint)
0:7 'i' ( temp uint)
0:7 Constant:
0:7 1 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
SPIR-V is not generated for failed compile or link
hlsl.waveordered2.frag
ERROR: 0:4: 'GlobalOrderedCountIncrement' : GlobalOrderedCountIncrement() unsupported
ERROR: 1 compilation errors. No code generated.
Shader version: 500
gl_FragCoord origin is upper left
ERROR: node is still EOpNull!
0:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Sequence
0:3 move second child to first child ( temp uint)
0:3 'i' ( temp uint)
0:3 Constant:
0:3 42 (const uint)
0:4 Test condition and select ( temp void)
0:4 Condition
0:4 Compare Equal ( temp bool)
0:4 Constant:
0:4 0 (const uint)
0:4 ERROR: Bad unary op
( temp uint)
0:4 'i' ( temp uint)
0:4 true case
0:? Sequence
0:6 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:4 false case
0:? Sequence
0:10 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( 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
ERROR: node is still EOpNull!
0:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Sequence
0:3 move second child to first child ( temp uint)
0:3 'i' ( temp uint)
0:3 Constant:
0:3 42 (const uint)
0:4 Test condition and select ( temp void)
0:4 Condition
0:4 Compare Equal ( temp bool)
0:4 Constant:
0:4 0 (const uint)
0:4 ERROR: Bad unary op
( temp uint)
0:4 'i' ( temp uint)
0:4 true case
0:? Sequence
0:6 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:4 false case
0:? Sequence
0:10 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( temp 4-component vector of float)
0:? Linker Objects
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
SPIR-V is not generated for failed compile or link
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
hlsl.wavequery.comp
Shader version: 500
local_size = (32, 16, 1)
0:? Sequence
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 move second child to first child ( temp uint)
0:6 indirect index (layout( row_major std430) buffer uint)
0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:6 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:6 Constant:
0:6 0 (const uint)
0:6 '@gl_SubgroupInvocationID' ( in uint unknown built-in variable)
0:6 Test condition and select ( temp uint)
0:6 Condition
0:6 subgroupElect ( temp bool)
0:6 true case
0:6 '@gl_SubgroupSize' ( in uint unknown built-in variable)
0:6 false case
0:6 Constant:
0:6 0 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
Linked compute stage:
Shader version: 500
local_size = (32, 16, 1)
0:? Sequence
0:5 Function Definition: @CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:6 move second child to first child ( temp uint)
0:6 indirect index (layout( row_major std430) buffer uint)
0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
0:6 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
0:6 Constant:
0:6 0 (const uint)
0:6 '@gl_SubgroupInvocationID' ( in uint unknown built-in variable)
0:6 Test condition and select ( temp uint)
0:6 Condition
0:6 subgroupElect ( temp bool)
0:6 true case
0:6 '@gl_SubgroupSize' ( in uint unknown built-in variable)
0:6 false case
0:6 Constant:
0:6 0 (const uint)
0:5 Function Definition: CSMain( ( temp void)
0:5 Function Parameters:
0:? Sequence
0:5 Function Call: @CSMain( ( temp void)
0:? Linker Objects
0:? 'data' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 28
Capability Shader
Capability GroupNonUniform
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "CSMain" 16 21
ExecutionMode 4 LocalSize 32 16 1
Source HLSL 500
Name 4 "CSMain"
Name 6 "@CSMain("
Name 10 "data"
MemberName 10(data) 0 "@data"
Name 12 "data"
Name 16 "@gl_SubgroupInvocationID"
Name 21 "@gl_SubgroupSize"
Decorate 9 ArrayStride 4
MemberDecorate 10(data) 0 Offset 0
Decorate 10(data) BufferBlock
Decorate 12(data) DescriptorSet 0
Decorate 16(@gl_SubgroupInvocationID) BuiltIn SubgroupLocalInvocationId
Decorate 21(@gl_SubgroupSize) BuiltIn SubgroupSize
2: TypeVoid
3: TypeFunction 2
8: TypeInt 32 0
9: TypeRuntimeArray 8(int)
10(data): TypeStruct 9
11: TypePointer Uniform 10(data)
12(data): 11(ptr) Variable Uniform
13: TypeInt 32 1
14: 13(int) Constant 0
15: TypePointer Input 8(int)
16(@gl_SubgroupInvocationID): 15(ptr) Variable Input
18: TypeBool
19: 8(int) Constant 3
21(@gl_SubgroupSize): 15(ptr) Variable Input
23: 8(int) Constant 0
25: TypePointer Uniform 8(int)
4(CSMain): 2 Function None 3
5: Label
27: 2 FunctionCall 6(@CSMain()
Return
FunctionEnd
6(@CSMain(): 2 Function None 3
7: Label
17: 8(int) Load 16(@gl_SubgroupInvocationID)
20: 18(bool) GroupNonUniformElect 19
22: 8(int) Load 21(@gl_SubgroupSize)
24: 8(int) Select 20 22 23
26: 25(ptr) AccessChain 12(data) 14 17
Store 26 24
Return
FunctionEnd
hlsl.wavequery.frag
Shader version: 500
gl_FragCoord origin is upper left
0:? Sequence
0:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Test condition and select ( temp void)
0:3 Condition
0:3 '@gl_HelperInvocation' ( in bool HelperInvocation)
0:3 true case
0:? Sequence
0:5 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:3 false case
0:? Sequence
0:9 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( 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:2 Function Definition: @PixelShaderFunction( ( temp 4-component vector of float)
0:2 Function Parameters:
0:? Sequence
0:3 Test condition and select ( temp void)
0:3 Condition
0:3 '@gl_HelperInvocation' ( in bool HelperInvocation)
0:3 true case
0:? Sequence
0:5 Branch: Return with expression
0:? Constant:
0:? 1.000000
0:? 2.000000
0:? 3.000000
0:? 4.000000
0:3 false case
0:? Sequence
0:9 Branch: Return with expression
0:? Constant:
0:? 4.000000
0:? 3.000000
0:? 2.000000
0:? 1.000000
0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters:
0:? Sequence
0:2 move second child to first child ( temp 4-component vector of float)
0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
0:2 Function Call: @PixelShaderFunction( ( 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 30
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction" 13 28
ExecutionMode 4 OriginUpperLeft
Source HLSL 500
Name 4 "PixelShaderFunction"
Name 9 "@PixelShaderFunction("
Name 13 "@gl_HelperInvocation"
Name 28 "@entryPointOutput"
Decorate 13(@gl_HelperInvocation) BuiltIn HelperInvocation
Decorate 28(@entryPointOutput) Location 0
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
7: TypeVector 6(float) 4
8: TypeFunction 7(fvec4)
11: TypeBool
12: TypePointer Input 11(bool)
13(@gl_HelperInvocation): 12(ptr) Variable Input
17: 6(float) Constant 1065353216
18: 6(float) Constant 1073741824
19: 6(float) Constant 1077936128
20: 6(float) Constant 1082130432
21: 7(fvec4) ConstantComposite 17 18 19 20
24: 7(fvec4) ConstantComposite 20 19 18 17
27: TypePointer Output 7(fvec4)
28(@entryPointOutput): 27(ptr) Variable Output
4(PixelShaderFunction): 2 Function None 3
5: Label
29: 7(fvec4) FunctionCall 9(@PixelShaderFunction()
Store 28(@entryPointOutput) 29
Return
FunctionEnd
9(@PixelShaderFunction(): 7(fvec4) Function None 8
10: Label
14: 11(bool) Load 13(@gl_HelperInvocation)
SelectionMerge 16 None
BranchConditional 14 15 23
15: Label
ReturnValue 21
23: Label
ReturnValue 24
16: Label
26: 7(fvec4) Undef
ReturnValue 26
FunctionEnd
This source diff could not be displayed because it is too large. You can view the blob instead.
struct Types
{
uint4 u;
int4 i;
float4 f;
double4 d;
};
RWStructuredBuffer<Types> data;
[numthreads(32, 16, 1)]
void CSMain(uint3 dti : SV_DispatchThreadID)
{
data[dti.x].u = WaveReadLaneAt(data[dti.x].u, 13);
data[dti.x].u.x = WaveReadLaneAt(data[dti.x].u.x, 13);
data[dti.x].u.xy = WaveReadLaneAt(data[dti.x].u.xy, 13);
data[dti.x].u.xyz = WaveReadLaneAt(data[dti.x].u.xyz, 13);
data[dti.x].i = WaveReadLaneAt(data[dti.x].i, 13);
data[dti.x].i.x = WaveReadLaneAt(data[dti.x].i.x, 13);
data[dti.x].i.xy = WaveReadLaneAt(data[dti.x].i.xy, 13);
data[dti.x].i.xyz = WaveReadLaneAt(data[dti.x].i.xyz, 13);
data[dti.x].f = WaveReadLaneAt(data[dti.x].f, 13);
data[dti.x].f.x = WaveReadLaneAt(data[dti.x].f.x, 13);
data[dti.x].f.xy = WaveReadLaneAt(data[dti.x].f.xy, 13);
data[dti.x].f.xyz = WaveReadLaneAt(data[dti.x].f.xyz, 13);
data[dti.x].d = WaveReadFirstLane(data[dti.x].d);
data[dti.x].d.x = WaveReadFirstLane(data[dti.x].d.x);
data[dti.x].d.xy = WaveReadFirstLane(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveReadFirstLane(data[dti.x].d.xyz);
data[dti.x].u = WaveReadFirstLane(data[dti.x].u);
data[dti.x].u.x = WaveReadFirstLane(data[dti.x].u.x);
data[dti.x].u.xy = WaveReadFirstLane(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveReadFirstLane(data[dti.x].u.xyz);
data[dti.x].i = WaveReadFirstLane(data[dti.x].i);
data[dti.x].i.x = WaveReadFirstLane(data[dti.x].i.x);
data[dti.x].i.xy = WaveReadFirstLane(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveReadFirstLane(data[dti.x].i.xyz);
data[dti.x].f = WaveReadFirstLane(data[dti.x].f);
data[dti.x].f.x = WaveReadFirstLane(data[dti.x].f.x);
data[dti.x].f.xy = WaveReadFirstLane(data[dti.x].f.xy);
data[dti.x].f.xyz = WaveReadFirstLane(data[dti.x].f.xyz);
data[dti.x].d = WaveReadFirstLane(data[dti.x].d);
data[dti.x].d.x = WaveReadFirstLane(data[dti.x].d.x);
data[dti.x].d.xy = WaveReadFirstLane(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveReadFirstLane(data[dti.x].d.xyz);
}
RWStructuredBuffer<uint> data;
[numthreads(32, 16, 1)]
void CSMain()
{
data[WaveGetOrderedIndex()] = 1;
}
float4 PixelShaderFunction() : COLOR0
{
if (0 == WaveGetOrderedIndex())
{
return float4(1, 2, 3, 4);
}
else
{
return float4(4, 3, 2, 1);
}
}
RWStructuredBuffer<uint> data;
[numthreads(32, 16, 1)]
void CSMain()
{
uint i = 42;
data[GlobalOrderedCountIncrement(i)] = 1;
}
float4 PixelShaderFunction() : COLOR0
{
uint i = 42;
if (0 == GlobalOrderedCountIncrement(i))
{
return float4(1, 2, 3, 4);
}
else
{
return float4(4, 3, 2, 1);
}
}
struct Types
{
uint4 u;
int4 i;
float4 f;
double4 d;
};
RWStructuredBuffer<Types> data;
[numthreads(32, 16, 1)]
void CSMain(uint3 dti : SV_DispatchThreadID)
{
data[dti.x].u = WavePrefixSum(data[dti.x].u);
data[dti.x].u.x = WavePrefixSum(data[dti.x].u.x);
data[dti.x].u.xy = WavePrefixSum(data[dti.x].u.xy);
data[dti.x].u.xyz = WavePrefixSum(data[dti.x].u.xyz);
data[dti.x].i = WavePrefixSum(data[dti.x].i);
data[dti.x].i.x = WavePrefixSum(data[dti.x].i.x);
data[dti.x].i.xy = WavePrefixSum(data[dti.x].i.xy);
data[dti.x].i.xyz = WavePrefixSum(data[dti.x].i.xyz);
data[dti.x].f = WavePrefixSum(data[dti.x].f);
data[dti.x].f.x = WavePrefixSum(data[dti.x].f.x);
data[dti.x].f.xy = WavePrefixSum(data[dti.x].f.xy);
data[dti.x].f.xyz = WavePrefixSum(data[dti.x].f.xyz);
data[dti.x].d = WavePrefixSum(data[dti.x].d);
data[dti.x].d.x = WavePrefixSum(data[dti.x].d.x);
data[dti.x].d.xy = WavePrefixSum(data[dti.x].d.xy);
data[dti.x].d.xyz = WavePrefixSum(data[dti.x].d.xyz);
data[dti.x].u = WavePrefixProduct(data[dti.x].u);
data[dti.x].u.x = WavePrefixProduct(data[dti.x].u.x);
data[dti.x].u.xy = WavePrefixProduct(data[dti.x].u.xy);
data[dti.x].u.xyz = WavePrefixProduct(data[dti.x].u.xyz);
data[dti.x].i = WavePrefixProduct(data[dti.x].i);
data[dti.x].i.x = WavePrefixProduct(data[dti.x].i.x);
data[dti.x].i.xy = WavePrefixProduct(data[dti.x].i.xy);
data[dti.x].i.xyz = WavePrefixProduct(data[dti.x].i.xyz);
data[dti.x].f = WavePrefixProduct(data[dti.x].f);
data[dti.x].f.x = WavePrefixProduct(data[dti.x].f.x);
data[dti.x].f.xy = WavePrefixProduct(data[dti.x].f.xy);
data[dti.x].f.xyz = WavePrefixProduct(data[dti.x].f.xyz);
data[dti.x].d = WavePrefixProduct(data[dti.x].d);
data[dti.x].d.x = WavePrefixProduct(data[dti.x].d.x);
data[dti.x].d.xy = WavePrefixProduct(data[dti.x].d.xy);
data[dti.x].d.xyz = WavePrefixProduct(data[dti.x].d.xyz);
}
struct Types
{
uint4 u;
int4 i;
float4 f;
double4 d;
};
RWStructuredBuffer<Types> data;
[numthreads(32, 16, 1)]
void CSMain(uint3 dti : SV_DispatchThreadID)
{
data[dti.x].u = QuadReadLaneAt(data[dti.x].u, 0);
data[dti.x].u.x = QuadReadLaneAt(data[dti.x].u.x, 0);
data[dti.x].u.xy = QuadReadLaneAt(data[dti.x].u.xy, 0);
data[dti.x].u.xyz = QuadReadLaneAt(data[dti.x].u.xyz, 0);
data[dti.x].i = QuadReadLaneAt(data[dti.x].i, 0);
data[dti.x].i.x = QuadReadLaneAt(data[dti.x].i.x, 0);
data[dti.x].i.xy = QuadReadLaneAt(data[dti.x].i.xy, 0);
data[dti.x].i.xyz = QuadReadLaneAt(data[dti.x].i.xyz, 0);
data[dti.x].f = QuadReadLaneAt(data[dti.x].f, 0);
data[dti.x].f.x = QuadReadLaneAt(data[dti.x].f.x, 0);
data[dti.x].f.xy = QuadReadLaneAt(data[dti.x].f.xy, 0);
data[dti.x].f.xyz = QuadReadLaneAt(data[dti.x].f.xyz, 0);
data[dti.x].d = QuadReadLaneAt(data[dti.x].d, 0);
data[dti.x].d.x = QuadReadLaneAt(data[dti.x].d.x, 0);
data[dti.x].d.xy = QuadReadLaneAt(data[dti.x].d.xy, 0);
data[dti.x].d.xyz = QuadReadLaneAt(data[dti.x].d.xyz, 0);
data[dti.x].u = QuadReadLaneAt(data[dti.x].u, 1);
data[dti.x].u.x = QuadReadLaneAt(data[dti.x].u.x, 1);
data[dti.x].u.xy = QuadReadLaneAt(data[dti.x].u.xy, 1);
data[dti.x].u.xyz = QuadReadLaneAt(data[dti.x].u.xyz, 1);
data[dti.x].i = QuadReadLaneAt(data[dti.x].i, 1);
data[dti.x].i.x = QuadReadLaneAt(data[dti.x].i.x, 1);
data[dti.x].i.xy = QuadReadLaneAt(data[dti.x].i.xy, 1);
data[dti.x].i.xyz = QuadReadLaneAt(data[dti.x].i.xyz, 1);
data[dti.x].f = QuadReadLaneAt(data[dti.x].f, 1);
data[dti.x].f.x = QuadReadLaneAt(data[dti.x].f.x, 1);
data[dti.x].f.xy = QuadReadLaneAt(data[dti.x].f.xy, 1);
data[dti.x].f.xyz = QuadReadLaneAt(data[dti.x].f.xyz, 1);
data[dti.x].d = QuadReadLaneAt(data[dti.x].d, 1);
data[dti.x].d.x = QuadReadLaneAt(data[dti.x].d.x, 1);
data[dti.x].d.xy = QuadReadLaneAt(data[dti.x].d.xy, 1);
data[dti.x].d.xyz = QuadReadLaneAt(data[dti.x].d.xyz, 1);
data[dti.x].u = QuadReadLaneAt(data[dti.x].u, 2);
data[dti.x].u.x = QuadReadLaneAt(data[dti.x].u.x, 2);
data[dti.x].u.xy = QuadReadLaneAt(data[dti.x].u.xy, 2);
data[dti.x].u.xyz = QuadReadLaneAt(data[dti.x].u.xyz, 2);
data[dti.x].i = QuadReadLaneAt(data[dti.x].i, 2);
data[dti.x].i.x = QuadReadLaneAt(data[dti.x].i.x, 2);
data[dti.x].i.xy = QuadReadLaneAt(data[dti.x].i.xy, 2);
data[dti.x].i.xyz = QuadReadLaneAt(data[dti.x].i.xyz, 2);
data[dti.x].f = QuadReadLaneAt(data[dti.x].f, 2);
data[dti.x].f.x = QuadReadLaneAt(data[dti.x].f.x, 2);
data[dti.x].f.xy = QuadReadLaneAt(data[dti.x].f.xy, 2);
data[dti.x].f.xyz = QuadReadLaneAt(data[dti.x].f.xyz, 2);
data[dti.x].d = QuadReadLaneAt(data[dti.x].d, 2);
data[dti.x].d.x = QuadReadLaneAt(data[dti.x].d.x, 2);
data[dti.x].d.xy = QuadReadLaneAt(data[dti.x].d.xy, 2);
data[dti.x].d.xyz = QuadReadLaneAt(data[dti.x].d.xyz, 2);
data[dti.x].u = QuadReadLaneAt(data[dti.x].u, 3);
data[dti.x].u.x = QuadReadLaneAt(data[dti.x].u.x, 3);
data[dti.x].u.xy = QuadReadLaneAt(data[dti.x].u.xy, 3);
data[dti.x].u.xyz = QuadReadLaneAt(data[dti.x].u.xyz, 3);
data[dti.x].i = QuadReadLaneAt(data[dti.x].i, 3);
data[dti.x].i.x = QuadReadLaneAt(data[dti.x].i.x, 3);
data[dti.x].i.xy = QuadReadLaneAt(data[dti.x].i.xy, 3);
data[dti.x].i.xyz = QuadReadLaneAt(data[dti.x].i.xyz, 3);
data[dti.x].f = QuadReadLaneAt(data[dti.x].f, 3);
data[dti.x].f.x = QuadReadLaneAt(data[dti.x].f.x, 3);
data[dti.x].f.xy = QuadReadLaneAt(data[dti.x].f.xy, 3);
data[dti.x].f.xyz = QuadReadLaneAt(data[dti.x].f.xyz, 3);
data[dti.x].d = QuadReadLaneAt(data[dti.x].d, 3);
data[dti.x].d.x = QuadReadLaneAt(data[dti.x].d.x, 3);
data[dti.x].d.xy = QuadReadLaneAt(data[dti.x].d.xy, 3);
data[dti.x].d.xyz = QuadReadLaneAt(data[dti.x].d.xyz, 3);
data[dti.x].u = QuadSwapX(data[dti.x].u);
data[dti.x].u.x = QuadSwapX(data[dti.x].u.x);
data[dti.x].u.xy = QuadSwapX(data[dti.x].u.xy);
data[dti.x].u.xyz = QuadSwapX(data[dti.x].u.xyz);
data[dti.x].i = QuadSwapX(data[dti.x].i);
data[dti.x].i.x = QuadSwapX(data[dti.x].i.x);
data[dti.x].i.xy = QuadSwapX(data[dti.x].i.xy);
data[dti.x].i.xyz = QuadSwapX(data[dti.x].i.xyz);
data[dti.x].f = QuadSwapX(data[dti.x].f);
data[dti.x].f.x = QuadSwapX(data[dti.x].f.x);
data[dti.x].f.xy = QuadSwapX(data[dti.x].f.xy);
data[dti.x].f.xyz = QuadSwapX(data[dti.x].f.xyz);
data[dti.x].d = QuadSwapX(data[dti.x].d);
data[dti.x].d.x = QuadSwapX(data[dti.x].d.x);
data[dti.x].d.xy = QuadSwapX(data[dti.x].d.xy);
data[dti.x].d.xyz = QuadSwapX(data[dti.x].d.xyz);
data[dti.x].u = QuadSwapY(data[dti.x].u);
data[dti.x].u.x = QuadSwapY(data[dti.x].u.x);
data[dti.x].u.xy = QuadSwapY(data[dti.x].u.xy);
data[dti.x].u.xyz = QuadSwapY(data[dti.x].u.xyz);
data[dti.x].i = QuadSwapY(data[dti.x].i);
data[dti.x].i.x = QuadSwapY(data[dti.x].i.x);
data[dti.x].i.xy = QuadSwapY(data[dti.x].i.xy);
data[dti.x].i.xyz = QuadSwapY(data[dti.x].i.xyz);
data[dti.x].f = QuadSwapY(data[dti.x].f);
data[dti.x].f.x = QuadSwapY(data[dti.x].f.x);
data[dti.x].f.xy = QuadSwapY(data[dti.x].f.xy);
data[dti.x].f.xyz = QuadSwapY(data[dti.x].f.xyz);
data[dti.x].d = QuadSwapY(data[dti.x].d);
data[dti.x].d.x = QuadSwapY(data[dti.x].d.x);
data[dti.x].d.xy = QuadSwapY(data[dti.x].d.xy);
data[dti.x].d.xyz = QuadSwapY(data[dti.x].d.xyz);
}
RWStructuredBuffer<uint> data;
[numthreads(32, 16, 1)]
void CSMain()
{
data[WaveGetLaneIndex()] = (WaveOnce()) ? WaveGetLaneCount() : 0;
}
float4 PixelShaderFunction() : COLOR0
{
if (WaveIsHelperLane())
{
return float4(1, 2, 3, 4);
}
else
{
return float4(4, 3, 2, 1);
}
}
struct Types
{
uint4 u;
int4 i;
float4 f;
double4 d;
};
RWStructuredBuffer<Types> data;
[numthreads(32, 16, 1)]
void CSMain(uint3 dti : SV_DispatchThreadID)
{
data[dti.x].u = WaveAllSum(data[dti.x].u);
data[dti.x].u.x = WaveAllSum(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllSum(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllSum(data[dti.x].u.xyz);
data[dti.x].i = WaveAllSum(data[dti.x].i);
data[dti.x].i.x = WaveAllSum(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllSum(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllSum(data[dti.x].i.xyz);
data[dti.x].f = WaveAllSum(data[dti.x].f);
data[dti.x].f.x = WaveAllSum(data[dti.x].f.x);
data[dti.x].f.xy = WaveAllSum(data[dti.x].f.xy);
data[dti.x].f.xyz = WaveAllSum(data[dti.x].f.xyz);
data[dti.x].d = WaveAllSum(data[dti.x].d);
data[dti.x].d.x = WaveAllSum(data[dti.x].d.x);
data[dti.x].d.xy = WaveAllSum(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveAllSum(data[dti.x].d.xyz);
data[dti.x].u = WaveAllProduct(data[dti.x].u);
data[dti.x].u.x = WaveAllProduct(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllProduct(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllProduct(data[dti.x].u.xyz);
data[dti.x].i = WaveAllProduct(data[dti.x].i);
data[dti.x].i.x = WaveAllProduct(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllProduct(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllProduct(data[dti.x].i.xyz);
data[dti.x].f = WaveAllProduct(data[dti.x].f);
data[dti.x].f.x = WaveAllProduct(data[dti.x].f.x);
data[dti.x].f.xy = WaveAllProduct(data[dti.x].f.xy);
data[dti.x].f.xyz = WaveAllProduct(data[dti.x].f.xyz);
data[dti.x].d = WaveAllProduct(data[dti.x].d);
data[dti.x].d.x = WaveAllProduct(data[dti.x].d.x);
data[dti.x].d.xy = WaveAllProduct(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveAllProduct(data[dti.x].d.xyz);
data[dti.x].u = WaveAllMin(data[dti.x].u);
data[dti.x].u.x = WaveAllMin(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllMin(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllMin(data[dti.x].u.xyz);
data[dti.x].i = WaveAllMin(data[dti.x].i);
data[dti.x].i.x = WaveAllMin(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllMin(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllMin(data[dti.x].i.xyz);
data[dti.x].f = WaveAllMin(data[dti.x].f);
data[dti.x].f.x = WaveAllMin(data[dti.x].f.x);
data[dti.x].f.xy = WaveAllMin(data[dti.x].f.xy);
data[dti.x].f.xyz = WaveAllMin(data[dti.x].f.xyz);
data[dti.x].d = WaveAllMin(data[dti.x].d);
data[dti.x].d.x = WaveAllMin(data[dti.x].d.x);
data[dti.x].d.xy = WaveAllMin(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveAllMin(data[dti.x].d.xyz);
data[dti.x].u = WaveAllMax(data[dti.x].u);
data[dti.x].u.x = WaveAllMax(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllMax(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllMax(data[dti.x].u.xyz);
data[dti.x].i = WaveAllMax(data[dti.x].i);
data[dti.x].i.x = WaveAllMax(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllMax(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllMax(data[dti.x].i.xyz);
data[dti.x].f = WaveAllMax(data[dti.x].f);
data[dti.x].f.x = WaveAllMax(data[dti.x].f.x);
data[dti.x].f.xy = WaveAllMax(data[dti.x].f.xy);
data[dti.x].f.xyz = WaveAllMax(data[dti.x].f.xyz);
data[dti.x].d = WaveAllMax(data[dti.x].d);
data[dti.x].d.x = WaveAllMax(data[dti.x].d.x);
data[dti.x].d.xy = WaveAllMax(data[dti.x].d.xy);
data[dti.x].d.xyz = WaveAllMax(data[dti.x].d.xyz);
data[dti.x].u = WaveAllBitAnd(data[dti.x].u);
data[dti.x].u.x = WaveAllBitAnd(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllBitAnd(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllBitAnd(data[dti.x].u.xyz);
data[dti.x].i = WaveAllBitAnd(data[dti.x].i);
data[dti.x].i.x = WaveAllBitAnd(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllBitAnd(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllBitAnd(data[dti.x].i.xyz);
data[dti.x].u = WaveAllBitOr(data[dti.x].u);
data[dti.x].u.x = WaveAllBitOr(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllBitOr(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllBitOr(data[dti.x].u.xyz);
data[dti.x].i = WaveAllBitOr(data[dti.x].i);
data[dti.x].i.x = WaveAllBitOr(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllBitOr(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllBitOr(data[dti.x].i.xyz);
data[dti.x].u = WaveAllBitXor(data[dti.x].u);
data[dti.x].u.x = WaveAllBitXor(data[dti.x].u.x);
data[dti.x].u.xy = WaveAllBitXor(data[dti.x].u.xy);
data[dti.x].u.xyz = WaveAllBitXor(data[dti.x].u.xyz);
data[dti.x].i = WaveAllBitXor(data[dti.x].i);
data[dti.x].i.x = WaveAllBitXor(data[dti.x].i.x);
data[dti.x].i.xy = WaveAllBitXor(data[dti.x].i.xy);
data[dti.x].i.xyz = WaveAllBitXor(data[dti.x].i.xyz);
}
RWStructuredBuffer<uint64_t> data;
[numthreads(32, 16, 1)]
void CSMain(uint3 dti : SV_DispatchThreadID)
{
data[dti.x] = WaveBallot(WaveAnyTrue(dti.x == 0));
data[dti.y] = WaveBallot(WaveAllTrue(dti.y == 0));
data[dti.z] = WaveBallot(WaveAllEqual(dti.z == 0));
}
...@@ -711,6 +711,14 @@ enum TOperator { ...@@ -711,6 +711,14 @@ enum TOperator {
// matrix // matrix
EOpMatrixSwizzle, // select multiple matrix components (non-column) EOpMatrixSwizzle, // select multiple matrix components (non-column)
// SM6 wave ops
EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize.
EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID.
EOpWaveIsHelperLane, // Will decompose to gl_HelperInvocation.
EOpWaveBallot, // Will decompose to subgroupBallot.
EOpWaveGetOrderedIndex, // Will decompose to an equation containing gl_SubgroupID.
EOpGlobalOrderedCountIncrement, // Will nice error.
}; };
class TIntermTraverser; class TIntermTraverser;
......
...@@ -697,11 +697,61 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node ...@@ -697,11 +697,61 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpWorkgroupMemoryBarrier: out.debug << "WorkgroupMemoryBarrier"; break; case EOpWorkgroupMemoryBarrier: out.debug << "WorkgroupMemoryBarrier"; break;
case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break; case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break;
case EOpSubgroupBarrier: out.debug << "subgroupBarrier"; break; case EOpSubgroupBarrier: out.debug << "subgroupBarrier"; break;
case EOpSubgroupMemoryBarrier: out.debug << "subgroupMemoryBarrier"; break; case EOpSubgroupMemoryBarrier: out.debug << "subgroupMemoryBarrier"; break;
case EOpSubgroupMemoryBarrierBuffer: out.debug << "subgroupMemoryBarrierBuffer"; break; case EOpSubgroupMemoryBarrierBuffer: out.debug << "subgroupMemoryBarrierBuffer"; break;
case EOpSubgroupMemoryBarrierImage: out.debug << "subgroupMemoryBarrierImage"; break; case EOpSubgroupMemoryBarrierImage: out.debug << "subgroupMemoryBarrierImage"; break;
case EOpSubgroupMemoryBarrierShared: out.debug << "subgroupMemoryBarrierShared"; break; case EOpSubgroupMemoryBarrierShared: out.debug << "subgroupMemoryBarrierShared"; break;
case EOpSubgroupElect: out.debug << "subgroupElect"; break;
case EOpSubgroupAll: out.debug << "subgroupAll"; break;
case EOpSubgroupAny: out.debug << "subgroupAny"; break;
case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break;
case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break;
case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break;
case EOpSubgroupBallot: out.debug << "subgroupBallot"; break;
case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break;
case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break;
case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break;
case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break;
case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break;
case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break;
case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break;
case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break;
case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break;
case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break;
case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break;
case EOpSubgroupAdd: out.debug << "subgroupAdd"; break;
case EOpSubgroupMul: out.debug << "subgroupMul"; break;
case EOpSubgroupMin: out.debug << "subgroupMin"; break;
case EOpSubgroupMax: out.debug << "subgroupMax"; break;
case EOpSubgroupAnd: out.debug << "subgroupAnd"; break;
case EOpSubgroupOr: out.debug << "subgroupOr"; break;
case EOpSubgroupXor: out.debug << "subgroupXor"; break;
case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break;
case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break;
case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break;
case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break;
case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break;
case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break;
case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break;
case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break;
case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break;
case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break;
case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break;
case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break;
case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break;
case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break;
case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break;
case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break;
case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break;
case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break;
case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break;
case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break;
case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break;
case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break;
case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break;
case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break;
case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break;
default: out.debug.message(EPrefixError, "Bad aggregation op"); default: out.debug.message(EPrefixError, "Bad aggregation op");
} }
......
...@@ -282,6 +282,17 @@ INSTANTIATE_TEST_CASE_P( ...@@ -282,6 +282,17 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.type.identifier.frag", "main"}, {"hlsl.type.identifier.frag", "main"},
{"hlsl.typeGraphCopy.vert", "main"}, {"hlsl.typeGraphCopy.vert", "main"},
{"hlsl.typedef.frag", "PixelShaderFunction"}, {"hlsl.typedef.frag", "PixelShaderFunction"},
{"hlsl.wavequery.comp", "CSMain"},
{"hlsl.wavequery.frag", "PixelShaderFunction"},
{"hlsl.wavevote.comp", "CSMain"},
{"hlsl.wavebroadcast.comp", "CSMain"},
{"hlsl.wavereduction.comp", "CSMain"},
{"hlsl.waveprefix.comp", "CSMain"},
{"hlsl.wavequad.comp", "CSMain"},
{"hlsl.waveordered.comp", "CSMain"},
{"hlsl.waveordered2.comp", "CSMain"},
{"hlsl.waveordered.frag", "PixelShaderFunction"},
{"hlsl.waveordered2.frag", "PixelShaderFunction"},
{"hlsl.whileLoop.frag", "PixelShaderFunction"}, {"hlsl.whileLoop.frag", "PixelShaderFunction"},
{"hlsl.void.frag", "PixelShaderFunction"}, {"hlsl.void.frag", "PixelShaderFunction"},
}), }),
......
...@@ -54,7 +54,7 @@ int main(int argc, char** argv) ...@@ -54,7 +54,7 @@ int main(int argc, char** argv)
glslangtest::GlobalTestSettings.updateMode = true; glslangtest::GlobalTestSettings.updateMode = true;
} }
if (std::string("--test-root") == argv[i]) { if (std::string("--test-root") == argv[i]) {
// Allow the user set the tets root directory. This is useful // Allow the user set the test root directory. This is useful
// for testing with files from another source tree. // for testing with files from another source tree.
if (i + 1 < argc) { if (i + 1 < argc) {
glslangtest::GlobalTestSettings.testRoot = argv[i + 1]; glslangtest::GlobalTestSettings.testRoot = argv[i + 1];
......
...@@ -1457,6 +1457,10 @@ bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList) ...@@ -1457,6 +1457,10 @@ bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
new(&type) TType(EbtUint, EvqTemporary, 4); new(&type) TType(EbtUint, EvqTemporary, 4);
break; break;
case EHTokUint64:
new(&type) TType(EbtUint64);
break;
case EHTokBool: case EHTokBool:
new(&type) TType(EbtBool); new(&type) TType(EbtBool);
break; break;
......
...@@ -3600,6 +3600,22 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& ...@@ -3600,6 +3600,22 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
return imageAggregate != nullptr && imageAggregate->getOp() == EOpImageLoad; return imageAggregate != nullptr && imageAggregate->getOp() == EOpImageLoad;
}; };
const auto lookupBuiltinVariable = [&](const char* name, TBuiltInVariable builtin, TType& type) -> TIntermTyped* {
TSymbol* symbol = symbolTable.find(name);
if (nullptr == symbol) {
type.getQualifier().builtIn = builtin;
TVariable* variable = new TVariable(new TString(name), type);
symbolTable.insert(*variable);
symbol = symbolTable.find(name);
assert(symbol && "Inserted symbol could not be found!");
}
return intermediate.addSymbol(*(symbol->getAsVariable()), loc);
};
// HLSL intrinsics can be pass through to native AST opcodes, or decomposed here to existing AST // HLSL intrinsics can be pass through to native AST opcodes, or decomposed here to existing AST
// opcodes for compatibility with existing software stacks. // opcodes for compatibility with existing software stacks.
static const bool decomposeHlslIntrinsics = true; static const bool decomposeHlslIntrinsics = true;
...@@ -4126,7 +4142,104 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& ...@@ -4126,7 +4142,104 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
break; break;
} }
case EOpWaveGetLaneCount:
{
// Mapped to gl_SubgroupSize builtin (We preprend @ to the symbol
// so that it inhabits the symbol table, but has a user-invalid name
// in-case some source HLSL defined the symbol also).
TType type(EbtUint, EvqVaryingIn);
node = lookupBuiltinVariable("@gl_SubgroupSize", EbvSubgroupSize2, type);
break;
}
case EOpWaveGetLaneIndex:
{
// Mapped to gl_SubgroupInvocationID builtin (We preprend @ to the
// symbol so that it inhabits the symbol table, but has a
// user-invalid name in-case some source HLSL defined the symbol
// also).
TType type(EbtUint, EvqVaryingIn);
node = lookupBuiltinVariable("@gl_SubgroupInvocationID", EbvSubgroupInvocation2, type);
break;
}
case EOpWaveIsHelperLane:
{
// Mapped to gl_HelperInvocation builtin (We preprend @ to the symbol
// so that it inhabits the symbol table, but has a user-invalid name
// in-case some source HLSL defined the symbol also).
TType type(EbtBool, EvqVaryingIn);
node = lookupBuiltinVariable("@gl_HelperInvocation", EbvHelperInvocation, type);
break;
}
case EOpWaveBallot:
{
// Mapped to subgroupBallot() builtin (NOTE: if an IHV has
// a subgroup size > 64 these wave ops will not work for them!)
// uvec4 type.
TType uvec4Type(EbtUint, EvqTemporary, 4);
// Get the uvec4 return from subgroupBallot().
TIntermTyped* res = intermediate.addBuiltInFunctionCall(loc,
EOpSubgroupBallot, true, arguments, uvec4Type);
// And extract a uvec2 for the two highest components.
TIntermTyped* xy = handleDotDereference(loc, res, "xy");
// uint64_t type.
TType uint64Type(EbtUint64, EvqTemporary);
// And bitcast the result for a uint64_t
node = intermediate.addBuiltInFunctionCall(loc,
EOpPackUint2x32, true, xy, uint64Type);
break;
}
case EOpWaveGetOrderedIndex:
{
if (language == EShLangFragment) {
// NOTE: For HLSL SM6.0 this should work for PS too, but the current GLSL extensions don't allow this.
error(loc, "WaveGetOrderedIndex() unsupported in a pixel/fragment shader", "WaveGetOrderedIndex", "");
break;
}
TType uintType(EbtUint, EvqVaryingIn);
TIntermTyped* subgroupID = lookupBuiltinVariable("@gl_SubgroupID", EbvSubgroupID, uintType);
TIntermTyped* numSubgroups = lookupBuiltinVariable("@gl_NumSubgroups", EbvNumSubgroups, uintType);
TType uvec3Type(EbtUint, EvqVaryingIn, 3);
TIntermTyped* numWorkGroups = lookupBuiltinVariable("@gl_NumWorkGroups", EbvNumWorkGroups, uvec3Type);
TIntermTyped* workGroupID = lookupBuiltinVariable("@gl_WorkGroupID", EbvWorkGroupId, uvec3Type);
//x & y components of gl_NumWorkGroups
TIntermTyped* numWorkGroupsX = handleDotDereference(loc, numWorkGroups, "x");
TIntermTyped* numWorkGroupsY = handleDotDereference(loc, numWorkGroups, "y");
// x & y components of globalSize
TIntermTyped* globalSizeX = handleBinaryMath(loc, "mul", EOpMul, numSubgroups, numWorkGroupsX);
TIntermTyped* globalSizeY = numWorkGroupsY;
// x, y & z components of gl_WorkGroupID
TIntermTyped* workGroupX = handleDotDereference(loc, workGroupID, "x");
TIntermTyped* workGroupY = handleDotDereference(loc, workGroupID, "y");
TIntermTyped* workGroupZ = handleDotDereference(loc, workGroupID, "z");
// We're going to build up the following variables to get a uniquely ordered ID:
// (globalSize.y * gl_WorkGroupID.z + gl_WorkGroupID.y) * globalSize.x + gl_WorkGroupID.x + gl_SubgroupID
node = handleBinaryMath(loc, "mul", EOpMul, globalSizeY, workGroupZ);
node = handleBinaryMath(loc, "add", EOpAdd, node, workGroupY);
node = handleBinaryMath(loc, "mul", EOpMul, node, globalSizeX);
node = handleBinaryMath(loc, "add", EOpAdd, node, workGroupX);
node = handleBinaryMath(loc, "add", EOpAdd, node, subgroupID);
break;
}
case EOpGlobalOrderedCountIncrement:
{
// NOTE: For HLSL SM6.0 this should work, but the current GLSL extensions don't allow this.
error(loc, "GlobalOrderedCountIncrement() unsupported", "GlobalOrderedCountIncrement", "");
break;
}
default: default:
break; // most pass through unchanged break; // most pass through unchanged
} }
......
...@@ -250,6 +250,8 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons ...@@ -250,6 +250,8 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
case 'D': s += "double"; break; case 'D': s += "double"; break;
case 'I': s += "int"; break; case 'I': s += "int"; break;
case 'U': s += "uint"; break; case 'U': s += "uint"; break;
case 'L': s += "int64_t"; break;
case 'M': s += "uint64_t"; break;
case 'B': s += "bool"; break; case 'B': s += "bool"; break;
case 'S': s += "sampler"; break; case 'S': s += "sampler"; break;
case 's': s += "SamplerComparisonState"; break; case 's': s += "SamplerComparisonState"; break;
...@@ -524,7 +526,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c ...@@ -524,7 +526,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
// orderKey can be: // orderKey can be:
// S = scalar, V = vector, M = matrix, - = void // S = scalar, V = vector, M = matrix, - = void
// typekey can be: // typekey can be:
// D = double, F = float, U = uint, I = int, B = bool, S = sampler, s = shadowSampler // D = double, F = float, U = uint, I = int, B = bool, S = sampler, s = shadowSampler, M = uint64_t, L = int64_t
// An empty order or type key repeats the first one. E.g: SVM,, means 3 args each of SVM. // An empty order or type key repeats the first one. E.g: SVM,, means 3 args each of SVM.
// '>' as first letter of order creates an output parameter // '>' as first letter of order creates an output parameter
// '<' as first letter of order creates an input parameter // '<' as first letter of order creates an input parameter
...@@ -875,6 +877,32 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c ...@@ -875,6 +877,32 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "DecrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true }, { "DecrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true },
{ "Consume", nullptr, nullptr, "-", "-", EShLangAll, true }, { "Consume", nullptr, nullptr, "-", "-", EShLangAll, true },
// SM 6.0
{ "WaveOnce", "S", "B", "-", "-", EShLangPSCS, false},
{ "WaveGetLaneCount", "S", "U", "-", "-", EShLangPSCS, false},
{ "WaveGetLaneIndex", "S", "U", "-", "-", EShLangPSCS, false},
{ "WaveIsHelperLane", "S", "B", "-", "-", EShLangPS, false},
{ "WaveAnyTrue", "S", "B", "S", "B", EShLangPSCS, false},
{ "WaveAllTrue", "S", "B", "S", "B", EShLangPSCS, false},
{ "WaveAllEqual", "S", "B", "S", "B", EShLangPSCS, false},
{ "WaveBallot", "S", "M", "S", "B", EShLangPSCS, false},
{ "WaveReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false},
{ "WaveReadFirstLane", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllMin", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllMax", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllBitAnd", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllBitOr", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveAllBitXor", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WavePrefixSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WavePrefixProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "QuadReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false},
{ "QuadSwapX", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "QuadSwapY", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveGetOrderedIndex", "S", "U", "-", "-", EShLangPSCS, false},
{ "GlobalOrderedCountIncrement", "S", "U", "S", "U", EShLangPSCS, false},
// Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet. // 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 }, { nullptr, nullptr, nullptr, nullptr, nullptr, 0, false },
}; };
...@@ -1211,6 +1239,32 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil ...@@ -1211,6 +1239,32 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil
// GS methods // GS methods
symbolTable.relateToOperator(BUILTIN_PREFIX "Append", EOpMethodAppend); symbolTable.relateToOperator(BUILTIN_PREFIX "Append", EOpMethodAppend);
symbolTable.relateToOperator(BUILTIN_PREFIX "RestartStrip", EOpMethodRestartStrip); symbolTable.relateToOperator(BUILTIN_PREFIX "RestartStrip", EOpMethodRestartStrip);
// Wave ops
symbolTable.relateToOperator("WaveOnce", EOpSubgroupElect);
symbolTable.relateToOperator("WaveGetLaneCount", EOpWaveGetLaneCount);
symbolTable.relateToOperator("WaveGetLaneIndex", EOpWaveGetLaneIndex);
symbolTable.relateToOperator("WaveIsHelperLane", EOpWaveIsHelperLane);
symbolTable.relateToOperator("WaveAnyTrue", EOpSubgroupAny);
symbolTable.relateToOperator("WaveAllTrue", EOpSubgroupAll);
symbolTable.relateToOperator("WaveAllEqual", EOpSubgroupAllEqual);
symbolTable.relateToOperator("WaveBallot", EOpWaveBallot);
symbolTable.relateToOperator("WaveReadLaneAt", EOpSubgroupShuffle);
symbolTable.relateToOperator("WaveReadFirstLane", EOpSubgroupBroadcastFirst);
symbolTable.relateToOperator("WaveAllSum", EOpSubgroupAdd);
symbolTable.relateToOperator("WaveAllProduct", EOpSubgroupMul);
symbolTable.relateToOperator("WaveAllMin", EOpSubgroupMin);
symbolTable.relateToOperator("WaveAllMax", EOpSubgroupMax);
symbolTable.relateToOperator("WaveAllBitAnd", EOpSubgroupAnd);
symbolTable.relateToOperator("WaveAllBitOr", EOpSubgroupOr);
symbolTable.relateToOperator("WaveAllBitXor", EOpSubgroupXor);
symbolTable.relateToOperator("WavePrefixSum", EOpSubgroupInclusiveAdd);
symbolTable.relateToOperator("WavePrefixProduct", EOpSubgroupInclusiveMul);
symbolTable.relateToOperator("QuadReadLaneAt", EOpSubgroupQuadBroadcast);
symbolTable.relateToOperator("QuadSwapX", EOpSubgroupQuadSwapHorizontal);
symbolTable.relateToOperator("QuadSwapY", EOpSubgroupQuadSwapVertical);
symbolTable.relateToOperator("WaveGetOrderedIndex", EOpWaveGetOrderedIndex);
symbolTable.relateToOperator("GlobalOrderedCountIncrement", EOpGlobalOrderedCountIncrement);
} }
// //
......
...@@ -143,6 +143,7 @@ void HlslScanContext::fillInKeywordMap() ...@@ -143,6 +143,7 @@ void HlslScanContext::fillInKeywordMap()
(*KeywordMap)["bool"] = EHTokBool; (*KeywordMap)["bool"] = EHTokBool;
(*KeywordMap)["int"] = EHTokInt; (*KeywordMap)["int"] = EHTokInt;
(*KeywordMap)["uint"] = EHTokUint; (*KeywordMap)["uint"] = EHTokUint;
(*KeywordMap)["uint64_t"] = EHTokUint64;
(*KeywordMap)["dword"] = EHTokDword; (*KeywordMap)["dword"] = EHTokDword;
(*KeywordMap)["half"] = EHTokHalf; (*KeywordMap)["half"] = EHTokHalf;
(*KeywordMap)["float"] = EHTokFloat; (*KeywordMap)["float"] = EHTokFloat;
...@@ -651,6 +652,7 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier() ...@@ -651,6 +652,7 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier()
case EHTokBool: case EHTokBool:
case EHTokInt: case EHTokInt:
case EHTokUint: case EHTokUint:
case EHTokUint64:
case EHTokDword: case EHTokDword:
case EHTokHalf: case EHTokHalf:
case EHTokFloat: case EHTokFloat:
......
...@@ -95,6 +95,7 @@ enum EHlslTokenClass { ...@@ -95,6 +95,7 @@ enum EHlslTokenClass {
EHTokBool, EHTokBool,
EHTokInt, EHTokInt,
EHTokUint, EHTokUint,
EHTokUint64,
EHTokDword, EHTokDword,
EHTokHalf, EHTokHalf,
EHTokFloat, EHTokFloat,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment