MSL: Handle interpolation qualifiers.

This commit is contained in:
Chip Davis 2018-09-04 16:08:22 -05:00
parent 301e5c8076
commit 9e6469bd40
17 changed files with 504 additions and 11 deletions

View File

@ -0,0 +1,39 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -0,0 +1,35 @@
#include <metal_stdlib>
#include <simd/simd.h>
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<float>(in.m_5);
v2.z = as_type<float>(in.m_6);
out.o0.y = float(as_type<uint>(as_type<float>(as_type<int>(v2.y) + as_type<int>(v2.z))));
out.o0.x = v1.y + v2.x;
out.o0 = float4(out.o0.x, out.o0.y, v1.z, v1.x);
return out;
}

View File

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

View File

@ -0,0 +1,28 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -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<float> uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]])

View File

@ -10,7 +10,7 @@ struct main0_out
struct main0_in
{
float2 vTex [[user(locn0)]];
float2 vTex [[user(locn0), flat]];
int vIndex [[user(locn1)]];
};

View File

@ -0,0 +1,39 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -0,0 +1,37 @@
#include <metal_stdlib>
#include <simd/simd.h>
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<float>(in.m_5);
v2.z = as_type<float>(in.m_6);
float4 r0;
r0.x = as_type<float>(as_type<int>(v2.y) + as_type<int>(v2.z));
out.o0.y = float(as_type<uint>(r0.x));
out.o0.x = v1.y + v2.x;
out.o0 = float4(out.o0.x, out.o0.y, v1.z, v1.x);
return out;
}

View File

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

View File

@ -0,0 +1,28 @@
#include <metal_stdlib>
#include <simd/simd.h>
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;
}

View File

@ -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<float> uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]])

View File

@ -12,7 +12,7 @@ struct main0_out
struct main0_in
{
float2 vTex [[user(locn0)]];
float2 vTex [[user(locn0), flat]];
int vIndex [[user(locn1)]];
};

View File

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

View File

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

View File

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

View File

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

View File

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