diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-07 13:38:31 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-07 14:00:40 +0300 |
commit | 1ec9d018fda4f595678c8f6b3f885b1004021b60 (patch) | |
tree | b14fb4e0edeae97c220e0f680cde71ae70483aa7 | |
parent | 213c5f42ea931db5206bdcc7ba8b1720bd1c83f5 (diff) |
MSL: Handle aliased variable names for resources placed in IB struct.
Just remember to register the names.
3 files changed, 178 insertions, 0 deletions
diff --git a/reference/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag b/reference/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag new file mode 100644 index 00000000..daeccaed --- /dev/null +++ b/reference/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag @@ -0,0 +1,105 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wmissing-braces" + +#include <metal_stdlib> +#include <simd/simd.h> + +using namespace metal; + +template<typename T, size_t Num> +struct spvUnsafeArray +{ + T elements[Num ? Num : 1]; + + thread T& operator [] (size_t pos) thread + { + return elements[pos]; + } + constexpr const thread T& operator [] (size_t pos) const thread + { + return elements[pos]; + } + + device T& operator [] (size_t pos) device + { + return elements[pos]; + } + constexpr const device T& operator [] (size_t pos) const device + { + return elements[pos]; + } + + constexpr const constant T& operator [] (size_t pos) const constant + { + return elements[pos]; + } + + threadgroup T& operator [] (size_t pos) threadgroup + { + return elements[pos]; + } + constexpr const threadgroup T& operator [] (size_t pos) const threadgroup + { + return elements[pos]; + } +}; + +struct Foo +{ + float a; + float b; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float ALIAS_0_a [[user(locn1)]]; + float ALIAS_0_b [[user(locn2)]]; + float ALIAS_1_a [[user(locn3)]]; + float ALIAS_1_b [[user(locn4)]]; + float ALIAS_2_a [[user(locn5)]]; + float ALIAS_2_b [[user(locn6)]]; + float ALIAS_3_a [[user(locn7)]]; + float ALIAS_3_b [[user(locn8)]]; + float ALIAS_1_0_a [[user(locn10)]]; + float ALIAS_1_0_b [[user(locn11)]]; + float ALIAS_1_1_a [[user(locn12)]]; + float ALIAS_1_1_b [[user(locn13)]]; + float ALIAS_1_2_a [[user(locn14)]]; + float ALIAS_1_2_b [[user(locn15)]]; + float ALIAS_1_3_a [[user(locn16)]]; + float ALIAS_1_3_b [[user(locn17)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + spvUnsafeArray<Foo, 4> ALIAS = {}; + spvUnsafeArray<Foo, 4> ALIAS_1 = {}; + ALIAS[0].a = in.ALIAS_0_a; + ALIAS[0].b = in.ALIAS_0_b; + ALIAS[1].a = in.ALIAS_1_a; + ALIAS[1].b = in.ALIAS_1_b; + ALIAS[2].a = in.ALIAS_2_a; + ALIAS[2].b = in.ALIAS_2_b; + ALIAS[3].a = in.ALIAS_3_a; + ALIAS[3].b = in.ALIAS_3_b; + ALIAS_1[0].a = in.ALIAS_1_0_a; + ALIAS_1[0].b = in.ALIAS_1_0_b; + ALIAS_1[1].a = in.ALIAS_1_1_a; + ALIAS_1[1].b = in.ALIAS_1_1_b; + ALIAS_1[2].a = in.ALIAS_1_2_a; + ALIAS_1[2].b = in.ALIAS_1_2_b; + ALIAS_1[3].a = in.ALIAS_1_3_a; + ALIAS_1[3].b = in.ALIAS_1_3_b; + out.FragColor.x = ALIAS[0].a; + out.FragColor.y = ALIAS[1].b; + out.FragColor.z = ALIAS[2].a; + out.FragColor.w = ALIAS_1[3].b; + return out; +} + diff --git a/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag b/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag new file mode 100644 index 00000000..1840c9b1 --- /dev/null +++ b/shaders-msl-no-opt/asm/frag/in_block_with_aliased_struct_and_name.asm.frag @@ -0,0 +1,65 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 40 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColor %foos %bars + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColor "FragColor" + OpName %Foo "Foo" + OpMemberName %Foo 0 "a" + OpMemberName %Foo 1 "b" + OpName %foos "ALIAS" + OpName %bars "ALIAS" + OpDecorate %FragColor Location 0 + OpDecorate %foos Location 1 + OpDecorate %bars Location 10 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %Foo = OpTypeStruct %float %float + %uint = OpTypeInt 32 0 + %uint_4 = OpConstant %uint 4 +%_arr_Foo_uint_4 = OpTypeArray %Foo %uint_4 +%_ptr_Input__arr_Foo_uint_4 = OpTypePointer Input %_arr_Foo_uint_4 + %foos = OpVariable %_ptr_Input__arr_Foo_uint_4 Input + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Input_float = OpTypePointer Input %float + %uint_0 = OpConstant %uint 0 +%_ptr_Output_float = OpTypePointer Output %float + %int_1 = OpConstant %int 1 + %uint_1 = OpConstant %uint 1 + %int_2 = OpConstant %int 2 + %uint_2 = OpConstant %uint 2 + %bars = OpVariable %_ptr_Input__arr_Foo_uint_4 Input + %int_3 = OpConstant %int 3 + %uint_3 = OpConstant %uint 3 + %main = OpFunction %void None %3 + %5 = OpLabel + %19 = OpAccessChain %_ptr_Input_float %foos %int_0 %int_0 + %20 = OpLoad %float %19 + %23 = OpAccessChain %_ptr_Output_float %FragColor %uint_0 + OpStore %23 %20 + %25 = OpAccessChain %_ptr_Input_float %foos %int_1 %int_1 + %26 = OpLoad %float %25 + %28 = OpAccessChain %_ptr_Output_float %FragColor %uint_1 + OpStore %28 %26 + %30 = OpAccessChain %_ptr_Input_float %foos %int_2 %int_0 + %31 = OpLoad %float %30 + %33 = OpAccessChain %_ptr_Output_float %FragColor %uint_2 + OpStore %33 %31 + %36 = OpAccessChain %_ptr_Input_float %bars %int_3 %int_1 + %37 = OpLoad %float %36 + %39 = OpAccessChain %_ptr_Output_float %FragColor %uint_3 + OpStore %39 %37 + OpReturn + OpFunctionEnd diff --git a/spirv_msl.cpp b/spirv_msl.cpp index be1e3841..d46dc484 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -3132,6 +3132,14 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st return; } + // If variable names alias, they will end up with wrong names in the interface struct, because + // there might be aliases in the member name cache and there would be a mismatch in fixup_in code. + // Make sure to register the variables as unique resource names ahead of time. + // This would normally conflict with the name cache when emitting local variables, + // but this happens in the setup stage, before we hit compilation loops. + // The name cache is cleared before we actually emit code, so this is safe. + add_resource_name(var.self); + if (var_type.basetype == SPIRType::Struct) { bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block; |