3bfb2f94d4
This allows shaders to declare and use pointer-type variables. Pointers may be loaded and stored, be the result of an `OpSelect`, be passed to and returned from functions, and even be passed as inputs to the `OpPhi` instruction. All types of pointers may be used as variable pointers. Variable pointers to storage buffers and workgroup memory may even be loaded from and stored to, as though they were ordinary variables. In addition, this enables using an interior pointer to an array as though it were an array pointer itself using the `OpPtrAccessChain` instruction. This is a rather large and involved change, mostly because this is somewhat complicated with a lot of moving parts. It's a wonder SPIRV-Cross's output is largely unchanged. Indeed, many of these changes are to accomplish exactly that! Perhaps the largest source of changes was the violation of the assumption that, when emitting types, the pointer type didn't matter. One of the test cases added by the change doesn't optimize very well; the output of `spirv-opt` here is invalid SPIR-V. I need to file a bug with SPIRV-Tools about this. I wanted to test that variable pointers to images worked too, but I couldn't figure out how to propagate the access qualifier properly--in MSL, it's part of the type, so getting this right is important. I've punted on that for now.
153 lines
6.7 KiB
Plaintext
153 lines
6.7 KiB
Plaintext
; SPIR-V
|
|
; Version: 1.3
|
|
; Generator: Khronos SPIR-V Tools Assembler; 0
|
|
; Bound: 89
|
|
; Schema: 0
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
|
|
OpExecutionMode %main LocalSize 1 1 1
|
|
OpSource GLSL 450
|
|
OpName %main "main"
|
|
OpName %foo "foo"
|
|
OpMemberName %foo 0 "a"
|
|
OpMemberName %foo 1 "b"
|
|
OpMemberName %foo 2 "c"
|
|
OpName %bar "bar"
|
|
OpMemberName %bar 0 "d"
|
|
OpName %baz "baz"
|
|
OpMemberName %baz 0 "e"
|
|
OpName %buf "buf"
|
|
OpName %buf2 "buf2"
|
|
OpName %cb "cb"
|
|
OpName %tgsm "tgsm"
|
|
OpName %sbuf "sbuf"
|
|
OpName %sbuf2 "sbuf2"
|
|
OpName %stgsm "stgsm"
|
|
OpName %select_buffer "select_buffer"
|
|
OpName %select_buffer_null "select_buffer_null"
|
|
OpName %select_tgsm "select_tgsm"
|
|
OpName %cur "cur"
|
|
OpMemberDecorate %foo 0 Offset 0
|
|
OpMemberDecorate %foo 1 Offset 512
|
|
OpMemberDecorate %foo 2 Offset 520
|
|
OpMemberDecorate %bar 0 Offset 0
|
|
OpMemberDecorate %baz 0 Offset 0
|
|
OpDecorate %foo Block
|
|
OpDecorate %bar Block
|
|
OpDecorate %baz Block
|
|
OpDecorate %buf DescriptorSet 0
|
|
OpDecorate %buf Binding 0
|
|
OpDecorate %cb DescriptorSet 0
|
|
OpDecorate %cb Binding 3
|
|
OpDecorate %buf2 DescriptorSet 0
|
|
OpDecorate %buf2 Binding 4
|
|
OpDecorate %_ptr_Workgroup_int ArrayStride 4
|
|
OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
|
|
OpDecorate %_arr_int_uint_128 ArrayStride 4
|
|
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
|
|
%void = OpTypeVoid
|
|
%22 = OpTypeFunction %void
|
|
%int = OpTypeInt 32 1
|
|
%uint = OpTypeInt 32 0
|
|
%v3uint = OpTypeVector %uint 3
|
|
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
|
|
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
|
|
%uint_128 = OpConstant %uint 128
|
|
%_arr_int_uint_128 = OpTypeArray %int %uint_128
|
|
%float = OpTypeFloat 32
|
|
%v2float = OpTypeVector %float 2
|
|
%foo = OpTypeStruct %_arr_int_uint_128 %uint %v2float
|
|
%_ptr_StorageBuffer_foo = OpTypePointer StorageBuffer %foo
|
|
%buf = OpVariable %_ptr_StorageBuffer_foo StorageBuffer
|
|
%bar = OpTypeStruct %int
|
|
%_ptr_Uniform_bar = OpTypePointer Uniform %bar
|
|
%cb = OpVariable %_ptr_Uniform_bar Uniform
|
|
%baz = OpTypeStruct %_arr_int_uint_128
|
|
%_ptr_StorageBuffer_baz = OpTypePointer StorageBuffer %baz
|
|
%buf2 = OpVariable %_ptr_StorageBuffer_baz StorageBuffer
|
|
%_ptr_Workgroup__arr_int_uint_128 = OpTypePointer Workgroup %_arr_int_uint_128
|
|
%tgsm = OpVariable %_ptr_Workgroup__arr_int_uint_128 Workgroup
|
|
%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
|
|
%_ptr_Private__ptr_StorageBuffer_int = OpTypePointer Private %_ptr_StorageBuffer_int
|
|
%sbuf = OpVariable %_ptr_Private__ptr_StorageBuffer_int Private
|
|
%sbuf2 = OpVariable %_ptr_Private__ptr_StorageBuffer_int Private
|
|
%_ptr_Workgroup_int = OpTypePointer Workgroup %int
|
|
%_ptr_Private__ptr_Workgroup_int = OpTypePointer Private %_ptr_Workgroup_int
|
|
%stgsm = OpVariable %_ptr_Private__ptr_Workgroup_int Private
|
|
%uint_0 = OpConstant %uint 0
|
|
%bool = OpTypeBool
|
|
%_ptr_Uniform_int = OpTypePointer Uniform %int
|
|
%44 = OpTypeFunction %_ptr_StorageBuffer_int
|
|
%int_0 = OpConstant %int 0
|
|
%uint_1 = OpConstant %uint 1
|
|
%47 = OpConstantNull %_ptr_StorageBuffer_int
|
|
%48 = OpTypeFunction %_ptr_Workgroup_int
|
|
%49 = OpConstantNull %_ptr_Workgroup_int
|
|
%_ptr_Function__ptr_Workgroup_int = OpTypePointer Function %_ptr_Workgroup_int
|
|
%select_buffer = OpFunction %_ptr_StorageBuffer_int None %44
|
|
%51 = OpLabel
|
|
%52 = OpAccessChain %_ptr_Uniform_int %cb %uint_0
|
|
%53 = OpLoad %int %52
|
|
%54 = OpINotEqual %bool %53 %int_0
|
|
%55 = OpAccessChain %_ptr_StorageBuffer_int %buf %uint_0 %uint_0
|
|
%56 = OpAccessChain %_ptr_StorageBuffer_int %buf2 %uint_0 %uint_0
|
|
%57 = OpSelect %_ptr_StorageBuffer_int %54 %55 %56
|
|
OpReturnValue %57
|
|
OpFunctionEnd
|
|
%select_buffer_null = OpFunction %_ptr_StorageBuffer_int None %44
|
|
%58 = OpLabel
|
|
%59 = OpAccessChain %_ptr_Uniform_int %cb %uint_0
|
|
%60 = OpLoad %int %59
|
|
%61 = OpINotEqual %bool %60 %int_0
|
|
%62 = OpAccessChain %_ptr_StorageBuffer_int %buf %uint_0 %uint_0
|
|
%63 = OpSelect %_ptr_StorageBuffer_int %61 %62 %47
|
|
OpReturnValue %63
|
|
OpFunctionEnd
|
|
%select_tgsm = OpFunction %_ptr_Workgroup_int None %48
|
|
%64 = OpLabel
|
|
%65 = OpAccessChain %_ptr_Uniform_int %cb %uint_0
|
|
%66 = OpLoad %int %65
|
|
%67 = OpINotEqual %bool %66 %int_0
|
|
%68 = OpAccessChain %_ptr_Workgroup_int %tgsm %uint_0
|
|
%69 = OpSelect %_ptr_Workgroup_int %67 %68 %49
|
|
OpReturnValue %69
|
|
OpFunctionEnd
|
|
%main = OpFunction %void None %22
|
|
%70 = OpLabel
|
|
%cur = OpVariable %_ptr_Function__ptr_Workgroup_int Function
|
|
%71 = OpFunctionCall %_ptr_StorageBuffer_int %select_buffer
|
|
OpStore %sbuf %71
|
|
%72 = OpFunctionCall %_ptr_StorageBuffer_int %select_buffer_null
|
|
OpStore %sbuf2 %72
|
|
%73 = OpFunctionCall %_ptr_Workgroup_int %select_tgsm
|
|
OpStore %stgsm %73
|
|
%74 = OpAccessChain %_ptr_StorageBuffer_int %buf %uint_0 %uint_0
|
|
%75 = OpLoad %_ptr_Workgroup_int %stgsm
|
|
%76 = OpCopyObject %_ptr_Workgroup_int %75
|
|
OpStore %cur %76
|
|
OpBranch %77
|
|
%77 = OpLabel
|
|
%78 = OpPhi %_ptr_StorageBuffer_int %74 %70 %79 %80
|
|
%81 = OpLoad %_ptr_Workgroup_int %cur
|
|
%82 = OpLoad %int %78
|
|
%83 = OpINotEqual %bool %82 %int_0
|
|
OpLoopMerge %85 %80 None
|
|
OpBranchConditional %83 %84 %85
|
|
%84 = OpLabel
|
|
%86 = OpLoad %int %81
|
|
%87 = OpIAdd %int %82 %86
|
|
OpStore %78 %87
|
|
OpStore %81 %87
|
|
OpBranch %80
|
|
%80 = OpLabel
|
|
%79 = OpPtrAccessChain %_ptr_StorageBuffer_int %78 %uint_1
|
|
%88 = OpPtrAccessChain %_ptr_Workgroup_int %81 %uint_1
|
|
OpStore %cur %88
|
|
OpBranch %77
|
|
%85 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|