diff --git a/reference/opt/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag b/reference/opt/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag new file mode 100644 index 00000000..63bdfe6e --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag @@ -0,0 +1,39 @@ +#include +#include + +using namespace metal; + +struct Input +{ + float2 v0; + float2 v1; + float3 v2; + float4 v3; + float v4; + float v5; + float v6; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 Input_v0 [[user(locn0)]]; + float2 Input_v1 [[user(locn1), center_no_perspective]]; + float3 Input_v2 [[user(locn2), centroid_perspective]]; + float4 Input_v3 [[user(locn3), centroid_no_perspective]]; + float Input_v4 [[user(locn4), sample_perspective]]; + float Input_v5 [[user(locn5), sample_no_perspective]]; + float Input_v6 [[user(locn6), flat]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.FragColor = float4(in.Input_v0.x + in.Input_v1.y, in.Input_v2.xy, ((in.Input_v3.w * in.Input_v4) + in.Input_v5) - in.Input_v6); + return out; +} + diff --git a/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag b/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag new file mode 100644 index 00000000..4ff01cb9 --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/locations-components.asm.frag @@ -0,0 +1,35 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 o0 [[color(0)]]; +}; + +struct main0_in +{ + float2 m_2 [[user(locn1)]]; + float m_3 [[user(locn1)]]; + float m_4 [[user(locn2), flat]]; + uint m_5 [[user(locn2)]]; + uint m_6 [[user(locn2)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + float4 v1; + v1 = float4(in.m_2.x, in.m_2.y, v1.z, v1.w); + v1.z = in.m_3; + float4 v2; + v2.x = in.m_4; + v2.y = as_type(in.m_5); + v2.z = as_type(in.m_6); + out.o0.y = float(as_type(as_type(as_type(v2.y) + as_type(v2.z)))); + out.o0.x = v1.y + v2.x; + out.o0 = float4(out.o0.x, out.o0.y, v1.z, v1.x); + return out; +} + diff --git a/reference/opt/shaders-msl/frag/fp16-packing.frag b/reference/opt/shaders-msl/frag/fp16-packing.frag index 358681f6..e21feb43 100644 --- a/reference/opt/shaders-msl/frag/fp16-packing.frag +++ b/reference/opt/shaders-msl/frag/fp16-packing.frag @@ -12,7 +12,7 @@ struct main0_out struct main0_in { uint FP16 [[user(locn0)]]; - float2 FP32 [[user(locn1)]]; + float2 FP32 [[user(locn1), flat]]; }; fragment main0_out main0(main0_in in [[stage_in]]) diff --git a/reference/opt/shaders-msl/frag/interpolation-qualifiers.frag b/reference/opt/shaders-msl/frag/interpolation-qualifiers.frag new file mode 100644 index 00000000..aff6e1b0 --- /dev/null +++ b/reference/opt/shaders-msl/frag/interpolation-qualifiers.frag @@ -0,0 +1,28 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 v0 [[user(locn0)]]; + float2 v1 [[user(locn1), center_no_perspective]]; + float3 v2 [[user(locn2), centroid_perspective]]; + float4 v3 [[user(locn3), centroid_no_perspective]]; + float v4 [[user(locn4), sample_perspective]]; + float v5 [[user(locn5), sample_no_perspective]]; + float v6 [[user(locn6), flat]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.FragColor = float4(in.v0.x + in.v1.y, in.v2.xy, ((in.v3.w * in.v4) + in.v5) - in.v6); + return out; +} + diff --git a/reference/opt/shaders-msl/frag/sampler-1d-lod.frag b/reference/opt/shaders-msl/frag/sampler-1d-lod.frag index 1da2036e..96914f80 100644 --- a/reference/opt/shaders-msl/frag/sampler-1d-lod.frag +++ b/reference/opt/shaders-msl/frag/sampler-1d-lod.frag @@ -10,7 +10,7 @@ struct main0_out struct main0_in { - float vTex [[user(locn0)]]; + float vTex [[user(locn0), flat]]; }; fragment main0_out main0(main0_in in [[stage_in]], texture1d uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]]) diff --git a/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag b/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag index 5e9c488d..ae37cf9a 100644 --- a/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag +++ b/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag @@ -10,7 +10,7 @@ struct main0_out struct main0_in { - float2 vTex [[user(locn0)]]; + float2 vTex [[user(locn0), flat]]; int vIndex [[user(locn1)]]; }; diff --git a/reference/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag b/reference/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag new file mode 100644 index 00000000..63bdfe6e --- /dev/null +++ b/reference/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag @@ -0,0 +1,39 @@ +#include +#include + +using namespace metal; + +struct Input +{ + float2 v0; + float2 v1; + float3 v2; + float4 v3; + float v4; + float v5; + float v6; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 Input_v0 [[user(locn0)]]; + float2 Input_v1 [[user(locn1), center_no_perspective]]; + float3 Input_v2 [[user(locn2), centroid_perspective]]; + float4 Input_v3 [[user(locn3), centroid_no_perspective]]; + float Input_v4 [[user(locn4), sample_perspective]]; + float Input_v5 [[user(locn5), sample_no_perspective]]; + float Input_v6 [[user(locn6), flat]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.FragColor = float4(in.Input_v0.x + in.Input_v1.y, in.Input_v2.xy, ((in.Input_v3.w * in.Input_v4) + in.Input_v5) - in.Input_v6); + return out; +} + diff --git a/reference/shaders-msl/asm/frag/locations-components.asm.frag b/reference/shaders-msl/asm/frag/locations-components.asm.frag new file mode 100644 index 00000000..ecc330db --- /dev/null +++ b/reference/shaders-msl/asm/frag/locations-components.asm.frag @@ -0,0 +1,37 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 o0 [[color(0)]]; +}; + +struct main0_in +{ + float2 m_2 [[user(locn1)]]; + float m_3 [[user(locn1)]]; + float m_4 [[user(locn2), flat]]; + uint m_5 [[user(locn2)]]; + uint m_6 [[user(locn2)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + float4 v1; + v1 = float4(in.m_2.x, in.m_2.y, v1.z, v1.w); + v1.z = in.m_3; + float4 v2; + v2.x = in.m_4; + v2.y = as_type(in.m_5); + v2.z = as_type(in.m_6); + float4 r0; + r0.x = as_type(as_type(v2.y) + as_type(v2.z)); + out.o0.y = float(as_type(r0.x)); + out.o0.x = v1.y + v2.x; + out.o0 = float4(out.o0.x, out.o0.y, v1.z, v1.x); + return out; +} + diff --git a/reference/shaders-msl/frag/fp16-packing.frag b/reference/shaders-msl/frag/fp16-packing.frag index 358681f6..e21feb43 100644 --- a/reference/shaders-msl/frag/fp16-packing.frag +++ b/reference/shaders-msl/frag/fp16-packing.frag @@ -12,7 +12,7 @@ struct main0_out struct main0_in { uint FP16 [[user(locn0)]]; - float2 FP32 [[user(locn1)]]; + float2 FP32 [[user(locn1), flat]]; }; fragment main0_out main0(main0_in in [[stage_in]]) diff --git a/reference/shaders-msl/frag/interpolation-qualifiers.frag b/reference/shaders-msl/frag/interpolation-qualifiers.frag new file mode 100644 index 00000000..aff6e1b0 --- /dev/null +++ b/reference/shaders-msl/frag/interpolation-qualifiers.frag @@ -0,0 +1,28 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 v0 [[user(locn0)]]; + float2 v1 [[user(locn1), center_no_perspective]]; + float3 v2 [[user(locn2), centroid_perspective]]; + float4 v3 [[user(locn3), centroid_no_perspective]]; + float v4 [[user(locn4), sample_perspective]]; + float v5 [[user(locn5), sample_no_perspective]]; + float v6 [[user(locn6), flat]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.FragColor = float4(in.v0.x + in.v1.y, in.v2.xy, ((in.v3.w * in.v4) + in.v5) - in.v6); + return out; +} + diff --git a/reference/shaders-msl/frag/sampler-1d-lod.frag b/reference/shaders-msl/frag/sampler-1d-lod.frag index 1da2036e..96914f80 100644 --- a/reference/shaders-msl/frag/sampler-1d-lod.frag +++ b/reference/shaders-msl/frag/sampler-1d-lod.frag @@ -10,7 +10,7 @@ struct main0_out struct main0_in { - float vTex [[user(locn0)]]; + float vTex [[user(locn0), flat]]; }; fragment main0_out main0(main0_in in [[stage_in]], texture1d uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]]) diff --git a/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag b/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag index 2aac7331..af5112c1 100644 --- a/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag +++ b/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag @@ -12,7 +12,7 @@ struct main0_out struct main0_in { - float2 vTex [[user(locn0)]]; + float2 vTex [[user(locn0), flat]]; int vIndex [[user(locn1)]]; }; diff --git a/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag b/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag new file mode 100644 index 00000000..bd6d06fa --- /dev/null +++ b/shaders-msl/asm/frag/interpolation-qualifiers-struct.asm.frag @@ -0,0 +1,85 @@ +; SPIR-V +; Version: 1.3 +; Generator: Khronos Glslang Reference Front End; 6 +; Bound: 51 +; Schema: 0 + OpCapability Shader + OpCapability SampleRateShading + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColor %inp + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColor "FragColor" + OpName %Input "Input" + OpMemberName %Input 0 "v0" + OpMemberName %Input 1 "v1" + OpMemberName %Input 2 "v2" + OpMemberName %Input 3 "v3" + OpMemberName %Input 4 "v4" + OpMemberName %Input 5 "v5" + OpMemberName %Input 6 "v6" + OpName %inp "inp" + OpDecorate %FragColor Location 0 + OpDecorate %inp Location 0 + OpMemberDecorate %Input 1 NoPerspective + OpMemberDecorate %Input 2 Centroid + OpMemberDecorate %Input 3 Centroid + OpMemberDecorate %Input 3 NoPerspective + OpMemberDecorate %Input 4 Sample + OpMemberDecorate %Input 5 Sample + OpMemberDecorate %Input 5 NoPerspective + OpMemberDecorate %Input 6 Flat + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %v2float = OpTypeVector %float 2 + %v3float = OpTypeVector %float 3 + %Input = OpTypeStruct %v2float %v2float %v3float %v4float %float %float %float +%_ptr_Input_Input = OpTypePointer Input %Input + %inp = OpVariable %_ptr_Input_Input Input + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_Input_float = OpTypePointer Input %float + %int_1 = OpConstant %int 1 + %uint_1 = OpConstant %uint 1 + %int_2 = OpConstant %int 2 +%_ptr_Input_v3float = OpTypePointer Input %v3float + %int_3 = OpConstant %int 3 + %uint_3 = OpConstant %uint 3 + %int_4 = OpConstant %int 4 + %int_5 = OpConstant %int 5 + %int_6 = OpConstant %int 6 + %main = OpFunction %void None %3 + %5 = OpLabel + %20 = OpAccessChain %_ptr_Input_float %inp %int_0 %uint_0 + %21 = OpLoad %float %20 + %24 = OpAccessChain %_ptr_Input_float %inp %int_1 %uint_1 + %25 = OpLoad %float %24 + %26 = OpFAdd %float %21 %25 + %29 = OpAccessChain %_ptr_Input_v3float %inp %int_2 + %30 = OpLoad %v3float %29 + %31 = OpVectorShuffle %v2float %30 %30 0 1 + %34 = OpAccessChain %_ptr_Input_float %inp %int_3 %uint_3 + %35 = OpLoad %float %34 + %37 = OpAccessChain %_ptr_Input_float %inp %int_4 + %38 = OpLoad %float %37 + %39 = OpFMul %float %35 %38 + %41 = OpAccessChain %_ptr_Input_float %inp %int_5 + %42 = OpLoad %float %41 + %43 = OpFAdd %float %39 %42 + %45 = OpAccessChain %_ptr_Input_float %inp %int_6 + %46 = OpLoad %float %45 + %47 = OpFSub %float %43 %46 + %48 = OpCompositeExtract %float %31 0 + %49 = OpCompositeExtract %float %31 1 + %50 = OpCompositeConstruct %v4float %26 %48 %49 %47 + OpStore %FragColor %50 + OpReturn + OpFunctionEnd diff --git a/shaders-msl/asm/frag/locations-components.asm.frag b/shaders-msl/asm/frag/locations-components.asm.frag new file mode 100644 index 00000000..bf8c6a69 --- /dev/null +++ b/shaders-msl/asm/frag/locations-components.asm.frag @@ -0,0 +1,102 @@ +; SPIR-V +; Version: 1.0 +; Generator: Wine VKD3D Shader Compiler; 0 +; Bound: 67 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %8 %16 %22 %28 %33 %o0 + OpName %main "main" + OpName %v1 "v1" + OpName %v2 "v2" + OpName %o0 "o0" + OpName %r0 "r0" + OpDecorate %8 Location 1 + OpDecorate %16 Location 1 + OpDecorate %16 Component 2 + OpDecorate %22 Location 2 + OpDecorate %22 Flat + OpDecorate %28 Location 2 + OpDecorate %28 Component 1 + OpDecorate %28 Flat + OpDecorate %33 Location 2 + OpDecorate %33 Component 2 + OpDecorate %33 Flat + OpDecorate %o0 Location 0 + %void = OpTypeVoid + %2 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v2float = OpTypeVector %float 2 +%_ptr_Input_v2float = OpTypePointer Input %v2float + %8 = OpVariable %_ptr_Input_v2float Input + %v4float = OpTypeVector %float 4 +%_ptr_Private_v4float = OpTypePointer Private %v4float + %v1 = OpVariable %_ptr_Private_v4float Private +%_ptr_Input_float = OpTypePointer Input %float + %16 = OpVariable %_ptr_Input_float Input +%_ptr_Private_float = OpTypePointer Private %float + %uint = OpTypeInt 32 0 + %uint_2 = OpConstant %uint 2 + %22 = OpVariable %_ptr_Input_float Input + %v2 = OpVariable %_ptr_Private_v4float Private + %uint_0 = OpConstant %uint 0 +%_ptr_Input_uint = OpTypePointer Input %uint + %28 = OpVariable %_ptr_Input_uint Input + %uint_1 = OpConstant %uint 1 + %33 = OpVariable %_ptr_Input_uint Input +%_ptr_Output_v4float = OpTypePointer Output %v4float + %o0 = OpVariable %_ptr_Output_v4float Output +%_ptr_Function_v4float = OpTypePointer Function %v4float + %int = OpTypeInt 32 1 +%_ptr_Function_float = OpTypePointer Function %float +%_ptr_Output_float = OpTypePointer Output %float + %main = OpFunction %void None %2 + %4 = OpLabel + %r0 = OpVariable %_ptr_Function_v4float Function + %12 = OpLoad %v2float %8 + %13 = OpLoad %v4float %v1 + %14 = OpVectorShuffle %v4float %13 %12 4 5 2 3 + OpStore %v1 %14 + %17 = OpLoad %float %16 + %21 = OpInBoundsAccessChain %_ptr_Private_float %v1 %uint_2 + OpStore %21 %17 + %24 = OpLoad %float %22 + %26 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_0 + OpStore %26 %24 + %29 = OpLoad %uint %28 + %30 = OpBitcast %float %29 + %32 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_1 + OpStore %32 %30 + %34 = OpLoad %uint %33 + %35 = OpBitcast %float %34 + %36 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_2 + OpStore %36 %35 + %42 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_1 + %43 = OpLoad %float %42 + %44 = OpBitcast %int %43 + %45 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_2 + %46 = OpLoad %float %45 + %47 = OpBitcast %int %46 + %48 = OpIAdd %int %44 %47 + %49 = OpBitcast %float %48 + %51 = OpInBoundsAccessChain %_ptr_Function_float %r0 %uint_0 + OpStore %51 %49 + %52 = OpInBoundsAccessChain %_ptr_Function_float %r0 %uint_0 + %53 = OpLoad %float %52 + %54 = OpBitcast %uint %53 + %55 = OpConvertUToF %float %54 + %57 = OpInBoundsAccessChain %_ptr_Output_float %o0 %uint_1 + OpStore %57 %55 + %58 = OpInBoundsAccessChain %_ptr_Private_float %v1 %uint_1 + %59 = OpLoad %float %58 + %60 = OpInBoundsAccessChain %_ptr_Private_float %v2 %uint_0 + %61 = OpLoad %float %60 + %62 = OpFAdd %float %59 %61 + %63 = OpInBoundsAccessChain %_ptr_Output_float %o0 %uint_0 + OpStore %63 %62 + %64 = OpLoad %v4float %v1 + %65 = OpLoad %v4float %o0 + %66 = OpVectorShuffle %v4float %65 %64 0 1 6 4 + OpStore %o0 %66 + OpReturn + OpFunctionEnd diff --git a/shaders-msl/frag/interpolation-qualifiers.frag b/shaders-msl/frag/interpolation-qualifiers.frag new file mode 100644 index 00000000..ef8a4807 --- /dev/null +++ b/shaders-msl/frag/interpolation-qualifiers.frag @@ -0,0 +1,15 @@ +#version 450 + +layout(location=0) in vec2 v0; +layout(location=1) in noperspective vec2 v1; +layout(location=2) in centroid vec3 v2; +layout(location=3) in centroid noperspective vec4 v3; +layout(location=4) in sample float v4; +layout(location=5) in sample noperspective float v5; +layout(location=6) in flat float v6; + +layout(location=0) out vec4 FragColor; + +void main() { + FragColor = vec4(v0.x + v1.y, v2.xy, v3.w * v4 + v5 - v6); +} diff --git a/spirv_common.hpp b/spirv_common.hpp index 0ea94fcb..630b9e3c 100644 --- a/spirv_common.hpp +++ b/spirv_common.hpp @@ -1291,6 +1291,11 @@ static inline bool type_is_floating_point(const SPIRType &type) { return type.basetype == SPIRType::Half || type.basetype == SPIRType::Float || type.basetype == SPIRType::Double; } + +static inline bool type_is_integral(const SPIRType &type) +{ + return type.basetype == SPIRType::Int || type.basetype == SPIRType::UInt || type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64; +} } // namespace spirv_cross #endif diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 857807a0..30411541 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -753,6 +753,10 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) { BuiltIn builtin; bool is_builtin = is_member_builtin(type, mbr_idx, &builtin); + bool is_flat = has_member_decoration(type.self, mbr_idx, DecorationFlat); + bool is_noperspective = has_member_decoration(type.self, mbr_idx, DecorationNoPerspective); + bool is_centroid = has_member_decoration(type.self, mbr_idx, DecorationCentroid); + bool is_sample = has_member_decoration(type.self, mbr_idx, DecorationSample); if (!is_builtin || has_active_builtin(builtin, storage)) { @@ -793,6 +797,16 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) if (builtin == BuiltInPosition) qual_pos_var_name = qual_var_name; } + + // Copy interpolation decorations if needed + if (is_flat) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationFlat); + if (is_noperspective) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationNoPerspective); + if (is_centroid) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationCentroid); + if (is_sample) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationSample); } mbr_idx++; } @@ -804,6 +818,10 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) { bool is_builtin = is_builtin_variable(*p_var); BuiltIn builtin = BuiltIn(get_decoration(p_var->self, DecorationBuiltIn)); + bool is_flat = has_decoration(p_var->self, DecorationFlat); + bool is_noperspective = has_decoration(p_var->self, DecorationNoPerspective); + bool is_centroid = has_decoration(p_var->self, DecorationCentroid); + bool is_sample = has_decoration(p_var->self, DecorationSample); if (!is_builtin || has_active_builtin(builtin, storage)) { @@ -863,6 +881,16 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) set_member_decoration(ib_type_id, ib_mbr_idx, DecorationIndex, index); } + // Copy interpolation decorations if needed + if (is_flat) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationFlat); + if (is_noperspective) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationNoPerspective); + if (is_centroid) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationCentroid); + if (is_sample) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationSample); + switch (storage) { case StorageClassInput: @@ -917,6 +945,16 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage) if (builtin == BuiltInPosition) qual_pos_var_name = qual_var_name; } + + // Copy interpolation decorations if needed + if (is_flat) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationFlat); + if (is_noperspective) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationNoPerspective); + if (is_centroid) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationCentroid); + if (is_sample) + set_member_decoration(ib_type_id, ib_mbr_idx, DecorationSample); } } } @@ -3095,6 +3133,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in // Fragment function inputs if (execution.model == ExecutionModelFragment && type.storage == StorageClassInput) { + string quals = ""; if (is_builtin) { switch (builtin) @@ -3105,15 +3144,56 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in case BuiltInSampleId: case BuiltInSampleMask: case BuiltInLayer: - return string(" [[") + builtin_qualifier(builtin) + "]]"; + quals = builtin_qualifier(builtin); default: - return ""; + break; } } - uint32_t locn = get_ordered_member_location(type.self, index); - if (locn != k_unknown_location) - return string(" [[user(locn") + convert_to_string(locn) + ")]]"; + else + { + uint32_t locn = get_ordered_member_location(type.self, index); + if (locn != k_unknown_location) + quals = string("user(locn") + convert_to_string(locn) + ")"; + } + // Don't bother decorating integers with the 'flat' attribute; it's + // the default (in fact, the only option). Also don't bother with the + // FragCoord builtin; it's always noperspective on Metal. + if (!type_is_integral(mbr_type) && (!is_builtin || builtin != BuiltInFragCoord)) + { + if (has_member_decoration(type.self, index, DecorationFlat)) + { + if (!quals.empty()) + quals += ", "; + quals += "flat"; + } + else if (has_member_decoration(type.self, index, DecorationCentroid)) + { + if (!quals.empty()) + quals += ", "; + if (has_member_decoration(type.self, index, DecorationNoPerspective)) + quals += "centroid_no_perspective"; + else + quals += "centroid_perspective"; + } + else if (has_member_decoration(type.self, index, DecorationSample)) + { + if (!quals.empty()) + quals += ", "; + if (has_member_decoration(type.self, index, DecorationNoPerspective)) + quals += "sample_no_perspective"; + else + quals += "sample_perspective"; + } + else if (has_member_decoration(type.self, index, DecorationNoPerspective)) + { + if (!quals.empty()) + quals += ", "; + quals += "center_no_perspective"; + } + } + if (!quals.empty()) + return " [[" + quals + "]]"; } // Fragment function outputs