MSL: Handle aliased variable names for resources placed in IB struct.

Just remember to register the names.
This commit is contained in:
Hans-Kristian Arntzen 2022-03-07 11:38:31 +01:00
parent 213c5f42ea
commit 1ec9d018fd
3 changed files with 178 additions and 0 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -3132,6 +3132,14 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
return; 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) if (var_type.basetype == SPIRType::Struct)
{ {
bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block; bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block;