MSL: Support pull-model interpolation on MSL 2.3+.
New in MSL 2.3 is a template that can be used in the place of a scalar type in a stage-in struct. This template has methods which interpolate the varying at the given points. Curiously, you can't set interpolation attributes on such a varying; perspective-correctness is encoded in the type, while interpolation must be done using one of the methods. This makes using this somewhat awkward from SPIRV-Cross, requiring us to jump through a bunch of hoops to make this all work. Using varyings from functions in particular is a pain point, requiring us to pass the stage-in struct itself around. An alternative is to pass references to the interpolants; except this will fall over badly with composite types, which naturally must be flattened. As with tessellation, dynamic indexing isn't supported with pull-model interpolation. This is because of the need to reference the original struct member in order to call one of the pull-model interpolation methods on it. Also, this is done at the variable level; this means that if one varying in a struct is used with the pull-model functions, then the entire struct is emitted as pull-model interpolants. For some reason, this was not documented in the MSL spec, though there is a property on `MTLDevice`, `supportsPullModelInterpolation`, indicating support for this, which *is* documented. This does not appear to be implemented yet for AMD: it returns `NO` from `supportsPullModelInterpolation`, and pipelines with shaders using the templates fail to compile. It *is* implemeted for Intel. It's probably also implemented for Apple GPUs: on Apple Silicon, OpenGL calls down to Metal, and it wouldn't be possible to use the interpolation functions without this implemented in Metal. Based on my testing, where SPIR-V and GLSL have the offset relative to the pixel center, in Metal it appears to be relative to the pixel's upper-left corner, as in HLSL. Therefore, I've added an offset 0.4375, i.e. one half minus one sixteenth, to all arguments to `interpolate_at_offset()`. This also fixes a long-standing bug: if a pull-model interpolation function is used on a varying, make sure that varying is declared. We were already doing this only for the AMD pull-model function, `interpolateAtVertexAMD()`; for reasons which are completely beyond me, we weren't doing this for the base interpolation functions. I also note that there are no tests for the interpolation functions for GLSL or HLSL.
This commit is contained in:
parent
2e1bdeb212
commit
aca9b6879a
@ -0,0 +1,181 @@
|
||||
#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 _13
|
||||
{
|
||||
float4 x;
|
||||
float4 y;
|
||||
float4 z;
|
||||
spvUnsafeArray<float4, 2> u;
|
||||
spvUnsafeArray<float2, 2> v;
|
||||
spvUnsafeArray<float, 3> w;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
interpolant<float4, interpolation::no_perspective> foo [[user(locn0)]];
|
||||
interpolant<float3, interpolation::perspective> bar [[user(locn1)]];
|
||||
interpolant<float2, interpolation::perspective> baz [[user(locn2)]];
|
||||
int sid [[user(locn3)]];
|
||||
interpolant<float2, interpolation::perspective> a_0 [[user(locn4)]];
|
||||
interpolant<float2, interpolation::perspective> a_1 [[user(locn5)]];
|
||||
interpolant<float2, interpolation::perspective> b_0 [[user(locn6)]];
|
||||
interpolant<float2, interpolation::perspective> b_1 [[user(locn7)]];
|
||||
interpolant<float2, interpolation::perspective> c_0 [[user(locn8)]];
|
||||
interpolant<float2, interpolation::perspective> c_1 [[user(locn9)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_x [[user(locn10)]];
|
||||
interpolant<float4, interpolation::no_perspective> m_13_y [[user(locn11)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_z [[user(locn12)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_u_0 [[user(locn13)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_u_1 [[user(locn14)]];
|
||||
interpolant<float2, interpolation::no_perspective> m_13_v_0 [[user(locn15)]];
|
||||
interpolant<float2, interpolation::no_perspective> m_13_v_1 [[user(locn16)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_0 [[user(locn17)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_1 [[user(locn18)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_2 [[user(locn19)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
spvUnsafeArray<float2, 2> a = {};
|
||||
_13 s = {};
|
||||
spvUnsafeArray<float2, 2> b = {};
|
||||
spvUnsafeArray<float2, 2> c = {};
|
||||
a[0] = in.a_0.interpolate_at_center();
|
||||
a[1] = in.a_1.interpolate_at_center();
|
||||
s.x = in.m_13_x.interpolate_at_center();
|
||||
s.y = in.m_13_y.interpolate_at_centroid();
|
||||
s.z = in.m_13_z.interpolate_at_sample(gl_SampleID);
|
||||
s.u[0] = in.m_13_u_0.interpolate_at_centroid();
|
||||
s.u[1] = in.m_13_u_1.interpolate_at_centroid();
|
||||
s.v[0] = in.m_13_v_0.interpolate_at_sample(gl_SampleID);
|
||||
s.v[1] = in.m_13_v_1.interpolate_at_sample(gl_SampleID);
|
||||
s.w[0] = in.m_13_w_0.interpolate_at_center();
|
||||
s.w[1] = in.m_13_w_1.interpolate_at_center();
|
||||
s.w[2] = in.m_13_w_2.interpolate_at_center();
|
||||
b[0] = in.b_0.interpolate_at_centroid();
|
||||
b[1] = in.b_1.interpolate_at_centroid();
|
||||
c[0] = in.c_0.interpolate_at_sample(gl_SampleID);
|
||||
c[1] = in.c_1.interpolate_at_sample(gl_SampleID);
|
||||
out.FragColor = in.foo.interpolate_at_center();
|
||||
out.FragColor += in.foo.interpolate_at_centroid();
|
||||
out.FragColor += in.foo.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.foo.interpolate_at_offset(float2(0.100000001490116119384765625) + 0.4375);
|
||||
float3 _65 = out.FragColor.xyz + in.bar.interpolate_at_centroid();
|
||||
out.FragColor = float4(_65.x, _65.y, _65.z, out.FragColor.w);
|
||||
float3 _71 = out.FragColor.xyz + in.bar.interpolate_at_centroid();
|
||||
out.FragColor = float4(_71.x, _71.y, _71.z, out.FragColor.w);
|
||||
float3 _78 = out.FragColor.xyz + in.bar.interpolate_at_sample(in.sid);
|
||||
out.FragColor = float4(_78.x, _78.y, _78.z, out.FragColor.w);
|
||||
float3 _84 = out.FragColor.xyz + in.bar.interpolate_at_offset(float2(-0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_84.x, _84.y, _84.z, out.FragColor.w);
|
||||
float2 _91 = out.FragColor.xy + b[0];
|
||||
out.FragColor = float4(_91.x, _91.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _98 = out.FragColor.xy + in.b_1.interpolate_at_centroid();
|
||||
out.FragColor = float4(_98.x, _98.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _105 = out.FragColor.xy + in.b_0.interpolate_at_sample(2);
|
||||
out.FragColor = float4(_105.x, _105.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _112 = out.FragColor.xy + in.b_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_112.x, _112.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _119 = out.FragColor.xy + c[0];
|
||||
out.FragColor = float4(_119.x, _119.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _127 = out.FragColor.xy + in.c_1.interpolate_at_centroid().xy;
|
||||
out.FragColor = float4(_127.x, _127.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _135 = out.FragColor.xy + in.c_0.interpolate_at_sample(2).yx;
|
||||
out.FragColor = float4(_135.x, _135.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _143 = out.FragColor.xy + in.c_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).xx;
|
||||
out.FragColor = float4(_143.x, _143.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor += s.x;
|
||||
out.FragColor += in.m_13_x.interpolate_at_centroid();
|
||||
out.FragColor += in.m_13_x.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.m_13_x.interpolate_at_offset(float2(0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor += s.y;
|
||||
out.FragColor += in.m_13_y.interpolate_at_centroid();
|
||||
out.FragColor += in.m_13_y.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.m_13_y.interpolate_at_offset(float2(-0.100000001490116119384765625) + 0.4375);
|
||||
float2 _184 = out.FragColor.xy + s.v[0];
|
||||
out.FragColor = float4(_184.x, _184.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _191 = out.FragColor.xy + in.m_13_v_1.interpolate_at_centroid();
|
||||
out.FragColor = float4(_191.x, _191.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _198 = out.FragColor.xy + in.m_13_v_0.interpolate_at_sample(2);
|
||||
out.FragColor = float4(_198.x, _198.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _205 = out.FragColor.xy + in.m_13_v_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_205.x, _205.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor.x += s.w[0];
|
||||
out.FragColor.x += in.m_13_w_1.interpolate_at_centroid();
|
||||
out.FragColor.x += in.m_13_w_0.interpolate_at_sample(2);
|
||||
out.FragColor.x += in.m_13_w_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
float2 _328 = out.FragColor.xy + in.baz.interpolate_at_sample(gl_SampleID);
|
||||
out.FragColor = float4(_328.x, _328.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor.x += in.baz.interpolate_at_centroid().x;
|
||||
out.FragColor.y += in.baz.interpolate_at_sample(3).y;
|
||||
out.FragColor.z += in.baz.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).y;
|
||||
float2 _353 = out.FragColor.xy + in.a_1.interpolate_at_centroid();
|
||||
out.FragColor = float4(_353.x, _353.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _360 = out.FragColor.xy + in.a_0.interpolate_at_sample(2);
|
||||
out.FragColor = float4(_360.x, _360.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _367 = out.FragColor.xy + in.a_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_367.x, _367.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor += s.z;
|
||||
float2 _379 = out.FragColor.xy + in.m_13_z.interpolate_at_centroid().yy;
|
||||
out.FragColor = float4(_379.x, _379.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _387 = out.FragColor.yz + in.m_13_z.interpolate_at_sample(3).xy;
|
||||
out.FragColor = float4(out.FragColor.x, _387.x, _387.y, out.FragColor.w);
|
||||
float2 _395 = out.FragColor.zw + in.m_13_z.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).wx;
|
||||
out.FragColor = float4(out.FragColor.x, out.FragColor.y, _395.x, _395.y);
|
||||
out.FragColor += s.u[0];
|
||||
out.FragColor += in.m_13_u_1.interpolate_at_centroid();
|
||||
out.FragColor += in.m_13_u_0.interpolate_at_sample(2);
|
||||
out.FragColor += in.m_13_u_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,187 @@
|
||||
#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 _13
|
||||
{
|
||||
float4 x;
|
||||
float4 y;
|
||||
float4 z;
|
||||
spvUnsafeArray<float4, 2> u;
|
||||
spvUnsafeArray<float2, 2> v;
|
||||
spvUnsafeArray<float, 3> w;
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
interpolant<float4, interpolation::no_perspective> foo [[user(locn0)]];
|
||||
interpolant<float3, interpolation::perspective> bar [[user(locn1)]];
|
||||
interpolant<float2, interpolation::perspective> baz [[user(locn2)]];
|
||||
int sid [[user(locn3)]];
|
||||
interpolant<float2, interpolation::perspective> a_0 [[user(locn4)]];
|
||||
interpolant<float2, interpolation::perspective> a_1 [[user(locn5)]];
|
||||
interpolant<float2, interpolation::perspective> b_0 [[user(locn6)]];
|
||||
interpolant<float2, interpolation::perspective> b_1 [[user(locn7)]];
|
||||
interpolant<float2, interpolation::perspective> c_0 [[user(locn8)]];
|
||||
interpolant<float2, interpolation::perspective> c_1 [[user(locn9)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_x [[user(locn10)]];
|
||||
interpolant<float4, interpolation::no_perspective> m_13_y [[user(locn11)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_z [[user(locn12)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_u_0 [[user(locn13)]];
|
||||
interpolant<float4, interpolation::perspective> m_13_u_1 [[user(locn14)]];
|
||||
interpolant<float2, interpolation::no_perspective> m_13_v_0 [[user(locn15)]];
|
||||
interpolant<float2, interpolation::no_perspective> m_13_v_1 [[user(locn16)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_0 [[user(locn17)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_1 [[user(locn18)]];
|
||||
interpolant<float, interpolation::perspective> m_13_w_2 [[user(locn19)]];
|
||||
};
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
void func(thread float4& FragColor, thread float2 baz, thread spvUnsafeArray<float2, 2> (&a), thread _13& s, thread main0_in& in)
|
||||
{
|
||||
float2 _237 = FragColor.xy + baz;
|
||||
FragColor = float4(_237.x, _237.y, FragColor.z, FragColor.w);
|
||||
FragColor.x += in.baz.interpolate_at_centroid().x;
|
||||
FragColor.y += in.baz.interpolate_at_sample(3).y;
|
||||
FragColor.z += in.baz.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).y;
|
||||
float2 _262 = FragColor.xy + in.a_1.interpolate_at_centroid();
|
||||
FragColor = float4(_262.x, _262.y, FragColor.z, FragColor.w);
|
||||
float2 _269 = FragColor.xy + in.a_0.interpolate_at_sample(2);
|
||||
FragColor = float4(_269.x, _269.y, FragColor.z, FragColor.w);
|
||||
float2 _276 = FragColor.xy + in.a_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
FragColor = float4(_276.x, _276.y, FragColor.z, FragColor.w);
|
||||
FragColor += s.z;
|
||||
float2 _288 = FragColor.xy + in.m_13_z.interpolate_at_centroid().yy;
|
||||
FragColor = float4(_288.x, _288.y, FragColor.z, FragColor.w);
|
||||
float2 _296 = FragColor.yz + in.m_13_z.interpolate_at_sample(3).xy;
|
||||
FragColor = float4(FragColor.x, _296.x, _296.y, FragColor.w);
|
||||
float2 _304 = FragColor.zw + in.m_13_z.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).wx;
|
||||
FragColor = float4(FragColor.x, FragColor.y, _304.x, _304.y);
|
||||
FragColor += s.u[0];
|
||||
FragColor += in.m_13_u_1.interpolate_at_centroid();
|
||||
FragColor += in.m_13_u_0.interpolate_at_sample(2);
|
||||
FragColor += in.m_13_u_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
spvUnsafeArray<float2, 2> a = {};
|
||||
_13 s = {};
|
||||
spvUnsafeArray<float2, 2> b = {};
|
||||
spvUnsafeArray<float2, 2> c = {};
|
||||
a[0] = in.a_0.interpolate_at_center();
|
||||
a[1] = in.a_1.interpolate_at_center();
|
||||
s.x = in.m_13_x.interpolate_at_center();
|
||||
s.y = in.m_13_y.interpolate_at_centroid();
|
||||
s.z = in.m_13_z.interpolate_at_sample(gl_SampleID);
|
||||
s.u[0] = in.m_13_u_0.interpolate_at_centroid();
|
||||
s.u[1] = in.m_13_u_1.interpolate_at_centroid();
|
||||
s.v[0] = in.m_13_v_0.interpolate_at_sample(gl_SampleID);
|
||||
s.v[1] = in.m_13_v_1.interpolate_at_sample(gl_SampleID);
|
||||
s.w[0] = in.m_13_w_0.interpolate_at_center();
|
||||
s.w[1] = in.m_13_w_1.interpolate_at_center();
|
||||
s.w[2] = in.m_13_w_2.interpolate_at_center();
|
||||
b[0] = in.b_0.interpolate_at_centroid();
|
||||
b[1] = in.b_1.interpolate_at_centroid();
|
||||
c[0] = in.c_0.interpolate_at_sample(gl_SampleID);
|
||||
c[1] = in.c_1.interpolate_at_sample(gl_SampleID);
|
||||
out.FragColor = in.foo.interpolate_at_center();
|
||||
out.FragColor += in.foo.interpolate_at_centroid();
|
||||
out.FragColor += in.foo.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.foo.interpolate_at_offset(float2(0.100000001490116119384765625) + 0.4375);
|
||||
float3 _65 = out.FragColor.xyz + in.bar.interpolate_at_centroid();
|
||||
out.FragColor = float4(_65.x, _65.y, _65.z, out.FragColor.w);
|
||||
float3 _71 = out.FragColor.xyz + in.bar.interpolate_at_centroid();
|
||||
out.FragColor = float4(_71.x, _71.y, _71.z, out.FragColor.w);
|
||||
float3 _78 = out.FragColor.xyz + in.bar.interpolate_at_sample(in.sid);
|
||||
out.FragColor = float4(_78.x, _78.y, _78.z, out.FragColor.w);
|
||||
float3 _84 = out.FragColor.xyz + in.bar.interpolate_at_offset(float2(-0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_84.x, _84.y, _84.z, out.FragColor.w);
|
||||
float2 _91 = out.FragColor.xy + b[0];
|
||||
out.FragColor = float4(_91.x, _91.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _98 = out.FragColor.xy + in.b_1.interpolate_at_centroid();
|
||||
out.FragColor = float4(_98.x, _98.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _105 = out.FragColor.xy + in.b_0.interpolate_at_sample(2);
|
||||
out.FragColor = float4(_105.x, _105.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _112 = out.FragColor.xy + in.b_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_112.x, _112.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _119 = out.FragColor.xy + c[0];
|
||||
out.FragColor = float4(_119.x, _119.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _127 = out.FragColor.xy + in.c_1.interpolate_at_centroid().xy;
|
||||
out.FragColor = float4(_127.x, _127.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _135 = out.FragColor.xy + in.c_0.interpolate_at_sample(2).yx;
|
||||
out.FragColor = float4(_135.x, _135.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _143 = out.FragColor.xy + in.c_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375).xx;
|
||||
out.FragColor = float4(_143.x, _143.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor += s.x;
|
||||
out.FragColor += in.m_13_x.interpolate_at_centroid();
|
||||
out.FragColor += in.m_13_x.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.m_13_x.interpolate_at_offset(float2(0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor += s.y;
|
||||
out.FragColor += in.m_13_y.interpolate_at_centroid();
|
||||
out.FragColor += in.m_13_y.interpolate_at_sample(in.sid);
|
||||
out.FragColor += in.m_13_y.interpolate_at_offset(float2(-0.100000001490116119384765625) + 0.4375);
|
||||
float2 _184 = out.FragColor.xy + s.v[0];
|
||||
out.FragColor = float4(_184.x, _184.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _191 = out.FragColor.xy + in.m_13_v_1.interpolate_at_centroid();
|
||||
out.FragColor = float4(_191.x, _191.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _198 = out.FragColor.xy + in.m_13_v_0.interpolate_at_sample(2);
|
||||
out.FragColor = float4(_198.x, _198.y, out.FragColor.z, out.FragColor.w);
|
||||
float2 _205 = out.FragColor.xy + in.m_13_v_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
out.FragColor = float4(_205.x, _205.y, out.FragColor.z, out.FragColor.w);
|
||||
out.FragColor.x += s.w[0];
|
||||
out.FragColor.x += in.m_13_w_1.interpolate_at_centroid();
|
||||
out.FragColor.x += in.m_13_w_0.interpolate_at_sample(2);
|
||||
out.FragColor.x += in.m_13_w_1.interpolate_at_offset(float2(-0.100000001490116119384765625, 0.100000001490116119384765625) + 0.4375);
|
||||
func(out.FragColor, in.baz.interpolate_at_sample(gl_SampleID), a, s, in);
|
||||
return out;
|
||||
}
|
||||
|
425
shaders-msl/asm/frag/pull-model-interpolation.asm.msl23.frag
Normal file
425
shaders-msl/asm/frag/pull-model-interpolation.asm.msl23.frag
Normal file
@ -0,0 +1,425 @@
|
||||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Khronos SPIR-V Tools Assembler; 0
|
||||
; Bound: 325
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpCapability SampleRateShading
|
||||
OpCapability InterpolationFunction
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %FragColor %baz %a %s %foo %sid %bar %b %c
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %func_ "func("
|
||||
OpName %FragColor "FragColor"
|
||||
OpName %baz "baz"
|
||||
OpName %a "a"
|
||||
OpName %_ ""
|
||||
OpMemberName %_ 0 "x"
|
||||
OpMemberName %_ 1 "y"
|
||||
OpMemberName %_ 2 "z"
|
||||
OpMemberName %_ 3 "u"
|
||||
OpMemberName %_ 4 "v"
|
||||
OpMemberName %_ 5 "w"
|
||||
OpName %s "s"
|
||||
OpName %foo "foo"
|
||||
OpName %sid "sid"
|
||||
OpName %bar "bar"
|
||||
OpName %b "b"
|
||||
OpName %c "c"
|
||||
OpDecorate %FragColor Location 0
|
||||
OpDecorate %baz Sample
|
||||
OpDecorate %baz Location 2
|
||||
OpDecorate %a Location 4
|
||||
OpDecorate %s Location 10
|
||||
OpDecorate %foo NoPerspective
|
||||
OpDecorate %foo Location 0
|
||||
OpDecorate %sid Flat
|
||||
OpDecorate %sid Location 3
|
||||
OpDecorate %bar Centroid
|
||||
OpDecorate %bar Location 1
|
||||
OpDecorate %b Centroid
|
||||
OpDecorate %b Location 6
|
||||
OpDecorate %c Sample
|
||||
OpDecorate %c Location 8
|
||||
OpMemberDecorate %_ 1 Centroid
|
||||
OpMemberDecorate %_ 1 NoPerspective
|
||||
OpMemberDecorate %_ 2 Sample
|
||||
OpMemberDecorate %_ 3 Centroid
|
||||
OpMemberDecorate %_ 4 Sample
|
||||
OpMemberDecorate %_ 4 NoPerspective
|
||||
%void = OpTypeVoid
|
||||
%15 = 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
|
||||
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||
%baz = OpVariable %_ptr_Input_v2float Input
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_0 = OpConstant %uint 0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%uint_1 = OpConstant %uint 1
|
||||
%int = OpTypeInt 32 1
|
||||
%int_3 = OpConstant %int 3
|
||||
%float_n0_100000001 = OpConstant %float -0.100000001
|
||||
%float_0_100000001 = OpConstant %float 0.100000001
|
||||
%30 = OpConstantComposite %v2float %float_n0_100000001 %float_0_100000001
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2
|
||||
%_ptr_Input__arr_v2float_uint_2 = OpTypePointer Input %_arr_v2float_uint_2
|
||||
%a = OpVariable %_ptr_Input__arr_v2float_uint_2 Input
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_2 = OpConstant %int 2
|
||||
%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
|
||||
%_ptr_Input__arr_v4float_uint_2 = OpTypePointer Input %_arr_v4float_uint_2
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_arr_float_uint_3 = OpTypeArray %float %uint_3
|
||||
%_ = OpTypeStruct %v4float %v4float %v4float %_arr_v4float_uint_2 %_arr_v2float_uint_2 %_arr_float_uint_3
|
||||
%_ptr_Input__ = OpTypePointer Input %_
|
||||
%s = OpVariable %_ptr_Input__ Input
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%foo = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%sid = OpVariable %_ptr_Input_int Input
|
||||
%44 = OpConstantComposite %v2float %float_0_100000001 %float_0_100000001
|
||||
%v3float = OpTypeVector %float 3
|
||||
%_ptr_Input_v3float = OpTypePointer Input %v3float
|
||||
%bar = OpVariable %_ptr_Input_v3float Input
|
||||
%47 = OpConstantComposite %v2float %float_n0_100000001 %float_n0_100000001
|
||||
%b = OpVariable %_ptr_Input__arr_v2float_uint_2 Input
|
||||
%c = OpVariable %_ptr_Input__arr_v2float_uint_2 Input
|
||||
%int_4 = OpConstant %int 4
|
||||
%int_5 = OpConstant %int 5
|
||||
%main = OpFunction %void None %15
|
||||
%50 = OpLabel
|
||||
%51 = OpLoad %v4float %foo
|
||||
OpStore %FragColor %51
|
||||
%52 = OpExtInst %v4float %1 InterpolateAtCentroid %foo
|
||||
%53 = OpLoad %v4float %FragColor
|
||||
%54 = OpFAdd %v4float %53 %52
|
||||
OpStore %FragColor %54
|
||||
%55 = OpLoad %int %sid
|
||||
%56 = OpExtInst %v4float %1 InterpolateAtSample %foo %55
|
||||
%57 = OpLoad %v4float %FragColor
|
||||
%58 = OpFAdd %v4float %57 %56
|
||||
OpStore %FragColor %58
|
||||
%59 = OpExtInst %v4float %1 InterpolateAtOffset %foo %44
|
||||
%60 = OpLoad %v4float %FragColor
|
||||
%61 = OpFAdd %v4float %60 %59
|
||||
OpStore %FragColor %61
|
||||
%62 = OpLoad %v3float %bar
|
||||
%63 = OpLoad %v4float %FragColor
|
||||
%64 = OpVectorShuffle %v3float %63 %63 0 1 2
|
||||
%65 = OpFAdd %v3float %64 %62
|
||||
%66 = OpLoad %v4float %FragColor
|
||||
%67 = OpVectorShuffle %v4float %66 %65 4 5 6 3
|
||||
OpStore %FragColor %67
|
||||
%68 = OpExtInst %v3float %1 InterpolateAtCentroid %bar
|
||||
%69 = OpLoad %v4float %FragColor
|
||||
%70 = OpVectorShuffle %v3float %69 %69 0 1 2
|
||||
%71 = OpFAdd %v3float %70 %68
|
||||
%72 = OpLoad %v4float %FragColor
|
||||
%73 = OpVectorShuffle %v4float %72 %71 4 5 6 3
|
||||
OpStore %FragColor %73
|
||||
%74 = OpLoad %int %sid
|
||||
%75 = OpExtInst %v3float %1 InterpolateAtSample %bar %74
|
||||
%76 = OpLoad %v4float %FragColor
|
||||
%77 = OpVectorShuffle %v3float %76 %76 0 1 2
|
||||
%78 = OpFAdd %v3float %77 %75
|
||||
%79 = OpLoad %v4float %FragColor
|
||||
%80 = OpVectorShuffle %v4float %79 %78 4 5 6 3
|
||||
OpStore %FragColor %80
|
||||
%81 = OpExtInst %v3float %1 InterpolateAtOffset %bar %47
|
||||
%82 = OpLoad %v4float %FragColor
|
||||
%83 = OpVectorShuffle %v3float %82 %82 0 1 2
|
||||
%84 = OpFAdd %v3float %83 %81
|
||||
%85 = OpLoad %v4float %FragColor
|
||||
%86 = OpVectorShuffle %v4float %85 %84 4 5 6 3
|
||||
OpStore %FragColor %86
|
||||
%87 = OpAccessChain %_ptr_Input_v2float %b %int_0
|
||||
%88 = OpLoad %v2float %87
|
||||
%89 = OpLoad %v4float %FragColor
|
||||
%90 = OpVectorShuffle %v2float %89 %89 0 1
|
||||
%91 = OpFAdd %v2float %90 %88
|
||||
%92 = OpLoad %v4float %FragColor
|
||||
%93 = OpVectorShuffle %v4float %92 %91 4 5 2 3
|
||||
OpStore %FragColor %93
|
||||
%94 = OpAccessChain %_ptr_Input_v2float %b %int_1
|
||||
%95 = OpExtInst %v2float %1 InterpolateAtCentroid %94
|
||||
%96 = OpLoad %v4float %FragColor
|
||||
%97 = OpVectorShuffle %v2float %96 %96 0 1
|
||||
%98 = OpFAdd %v2float %97 %95
|
||||
%99 = OpLoad %v4float %FragColor
|
||||
%100 = OpVectorShuffle %v4float %99 %98 4 5 2 3
|
||||
OpStore %FragColor %100
|
||||
%101 = OpAccessChain %_ptr_Input_v2float %b %int_0
|
||||
%102 = OpExtInst %v2float %1 InterpolateAtSample %101 %int_2
|
||||
%103 = OpLoad %v4float %FragColor
|
||||
%104 = OpVectorShuffle %v2float %103 %103 0 1
|
||||
%105 = OpFAdd %v2float %104 %102
|
||||
%106 = OpLoad %v4float %FragColor
|
||||
%107 = OpVectorShuffle %v4float %106 %105 4 5 2 3
|
||||
OpStore %FragColor %107
|
||||
%108 = OpAccessChain %_ptr_Input_v2float %b %int_1
|
||||
%109 = OpExtInst %v2float %1 InterpolateAtOffset %108 %30
|
||||
%110 = OpLoad %v4float %FragColor
|
||||
%111 = OpVectorShuffle %v2float %110 %110 0 1
|
||||
%112 = OpFAdd %v2float %111 %109
|
||||
%113 = OpLoad %v4float %FragColor
|
||||
%114 = OpVectorShuffle %v4float %113 %112 4 5 2 3
|
||||
OpStore %FragColor %114
|
||||
%115 = OpAccessChain %_ptr_Input_v2float %c %int_0
|
||||
%116 = OpLoad %v2float %115
|
||||
%117 = OpLoad %v4float %FragColor
|
||||
%118 = OpVectorShuffle %v2float %117 %117 0 1
|
||||
%119 = OpFAdd %v2float %118 %116
|
||||
%120 = OpLoad %v4float %FragColor
|
||||
%121 = OpVectorShuffle %v4float %120 %119 4 5 2 3
|
||||
OpStore %FragColor %121
|
||||
%122 = OpAccessChain %_ptr_Input_v2float %c %int_1
|
||||
%123 = OpExtInst %v2float %1 InterpolateAtCentroid %122
|
||||
%124 = OpVectorShuffle %v2float %123 %123 0 1
|
||||
%125 = OpLoad %v4float %FragColor
|
||||
%126 = OpVectorShuffle %v2float %125 %125 0 1
|
||||
%127 = OpFAdd %v2float %126 %124
|
||||
%128 = OpLoad %v4float %FragColor
|
||||
%129 = OpVectorShuffle %v4float %128 %127 4 5 2 3
|
||||
OpStore %FragColor %129
|
||||
%130 = OpAccessChain %_ptr_Input_v2float %c %int_0
|
||||
%131 = OpExtInst %v2float %1 InterpolateAtSample %130 %int_2
|
||||
%132 = OpVectorShuffle %v2float %131 %131 1 0
|
||||
%133 = OpLoad %v4float %FragColor
|
||||
%134 = OpVectorShuffle %v2float %133 %133 0 1
|
||||
%135 = OpFAdd %v2float %134 %132
|
||||
%136 = OpLoad %v4float %FragColor
|
||||
%137 = OpVectorShuffle %v4float %136 %135 4 5 2 3
|
||||
OpStore %FragColor %137
|
||||
%138 = OpAccessChain %_ptr_Input_v2float %c %int_1
|
||||
%139 = OpExtInst %v2float %1 InterpolateAtOffset %138 %30
|
||||
%140 = OpVectorShuffle %v2float %139 %139 0 0
|
||||
%141 = OpLoad %v4float %FragColor
|
||||
%142 = OpVectorShuffle %v2float %141 %141 0 1
|
||||
%143 = OpFAdd %v2float %142 %140
|
||||
%144 = OpLoad %v4float %FragColor
|
||||
%145 = OpVectorShuffle %v4float %144 %143 4 5 2 3
|
||||
OpStore %FragColor %145
|
||||
%146 = OpAccessChain %_ptr_Input_v4float %s %int_0
|
||||
%147 = OpLoad %v4float %146
|
||||
%148 = OpLoad %v4float %FragColor
|
||||
%149 = OpFAdd %v4float %148 %147
|
||||
OpStore %FragColor %149
|
||||
%150 = OpAccessChain %_ptr_Input_v4float %s %int_0
|
||||
%151 = OpExtInst %v4float %1 InterpolateAtCentroid %150
|
||||
%152 = OpLoad %v4float %FragColor
|
||||
%153 = OpFAdd %v4float %152 %151
|
||||
OpStore %FragColor %153
|
||||
%154 = OpAccessChain %_ptr_Input_v4float %s %int_0
|
||||
%155 = OpLoad %int %sid
|
||||
%156 = OpExtInst %v4float %1 InterpolateAtSample %154 %155
|
||||
%157 = OpLoad %v4float %FragColor
|
||||
%158 = OpFAdd %v4float %157 %156
|
||||
OpStore %FragColor %158
|
||||
%159 = OpAccessChain %_ptr_Input_v4float %s %int_0
|
||||
%160 = OpExtInst %v4float %1 InterpolateAtOffset %159 %44
|
||||
%161 = OpLoad %v4float %FragColor
|
||||
%162 = OpFAdd %v4float %161 %160
|
||||
OpStore %FragColor %162
|
||||
%163 = OpAccessChain %_ptr_Input_v4float %s %int_1
|
||||
%164 = OpLoad %v4float %163
|
||||
%165 = OpLoad %v4float %FragColor
|
||||
%166 = OpFAdd %v4float %165 %164
|
||||
OpStore %FragColor %166
|
||||
%167 = OpAccessChain %_ptr_Input_v4float %s %int_1
|
||||
%168 = OpExtInst %v4float %1 InterpolateAtCentroid %167
|
||||
%169 = OpLoad %v4float %FragColor
|
||||
%170 = OpFAdd %v4float %169 %168
|
||||
OpStore %FragColor %170
|
||||
%171 = OpAccessChain %_ptr_Input_v4float %s %int_1
|
||||
%172 = OpLoad %int %sid
|
||||
%173 = OpExtInst %v4float %1 InterpolateAtSample %171 %172
|
||||
%174 = OpLoad %v4float %FragColor
|
||||
%175 = OpFAdd %v4float %174 %173
|
||||
OpStore %FragColor %175
|
||||
%176 = OpAccessChain %_ptr_Input_v4float %s %int_1
|
||||
%177 = OpExtInst %v4float %1 InterpolateAtOffset %176 %47
|
||||
%178 = OpLoad %v4float %FragColor
|
||||
%179 = OpFAdd %v4float %178 %177
|
||||
OpStore %FragColor %179
|
||||
%180 = OpAccessChain %_ptr_Input_v2float %s %int_4 %int_0
|
||||
%181 = OpLoad %v2float %180
|
||||
%182 = OpLoad %v4float %FragColor
|
||||
%183 = OpVectorShuffle %v2float %182 %182 0 1
|
||||
%184 = OpFAdd %v2float %183 %181
|
||||
%185 = OpLoad %v4float %FragColor
|
||||
%186 = OpVectorShuffle %v4float %185 %184 4 5 2 3
|
||||
OpStore %FragColor %186
|
||||
%187 = OpAccessChain %_ptr_Input_v2float %s %int_4 %int_1
|
||||
%188 = OpExtInst %v2float %1 InterpolateAtCentroid %187
|
||||
%189 = OpLoad %v4float %FragColor
|
||||
%190 = OpVectorShuffle %v2float %189 %189 0 1
|
||||
%191 = OpFAdd %v2float %190 %188
|
||||
%192 = OpLoad %v4float %FragColor
|
||||
%193 = OpVectorShuffle %v4float %192 %191 4 5 2 3
|
||||
OpStore %FragColor %193
|
||||
%194 = OpAccessChain %_ptr_Input_v2float %s %int_4 %int_0
|
||||
%195 = OpExtInst %v2float %1 InterpolateAtSample %194 %int_2
|
||||
%196 = OpLoad %v4float %FragColor
|
||||
%197 = OpVectorShuffle %v2float %196 %196 0 1
|
||||
%198 = OpFAdd %v2float %197 %195
|
||||
%199 = OpLoad %v4float %FragColor
|
||||
%200 = OpVectorShuffle %v4float %199 %198 4 5 2 3
|
||||
OpStore %FragColor %200
|
||||
%201 = OpAccessChain %_ptr_Input_v2float %s %int_4 %int_1
|
||||
%202 = OpExtInst %v2float %1 InterpolateAtOffset %201 %30
|
||||
%203 = OpLoad %v4float %FragColor
|
||||
%204 = OpVectorShuffle %v2float %203 %203 0 1
|
||||
%205 = OpFAdd %v2float %204 %202
|
||||
%206 = OpLoad %v4float %FragColor
|
||||
%207 = OpVectorShuffle %v4float %206 %205 4 5 2 3
|
||||
OpStore %FragColor %207
|
||||
%208 = OpAccessChain %_ptr_Input_float %s %int_5 %int_0
|
||||
%209 = OpLoad %float %208
|
||||
%210 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
%211 = OpLoad %float %210
|
||||
%212 = OpFAdd %float %211 %209
|
||||
%213 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
OpStore %213 %212
|
||||
%214 = OpAccessChain %_ptr_Input_float %s %int_5 %int_1
|
||||
%215 = OpExtInst %float %1 InterpolateAtCentroid %214
|
||||
%216 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
%217 = OpLoad %float %216
|
||||
%218 = OpFAdd %float %217 %215
|
||||
%219 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
OpStore %219 %218
|
||||
%220 = OpAccessChain %_ptr_Input_float %s %int_5 %int_0
|
||||
%221 = OpExtInst %float %1 InterpolateAtSample %220 %int_2
|
||||
%222 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
%223 = OpLoad %float %222
|
||||
%224 = OpFAdd %float %223 %221
|
||||
%225 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
OpStore %225 %224
|
||||
%226 = OpAccessChain %_ptr_Input_float %s %int_5 %int_1
|
||||
%227 = OpExtInst %float %1 InterpolateAtOffset %226 %30
|
||||
%228 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
%229 = OpLoad %float %228
|
||||
%230 = OpFAdd %float %229 %227
|
||||
%231 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
OpStore %231 %230
|
||||
%232 = OpFunctionCall %void %func_
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%func_ = OpFunction %void None %15
|
||||
%233 = OpLabel
|
||||
%234 = OpLoad %v2float %baz
|
||||
%235 = OpLoad %v4float %FragColor
|
||||
%236 = OpVectorShuffle %v2float %235 %235 0 1
|
||||
%237 = OpFAdd %v2float %236 %234
|
||||
%238 = OpLoad %v4float %FragColor
|
||||
%239 = OpVectorShuffle %v4float %238 %237 4 5 2 3
|
||||
OpStore %FragColor %239
|
||||
%240 = OpAccessChain %_ptr_Input_float %baz %uint_0
|
||||
%241 = OpExtInst %float %1 InterpolateAtCentroid %240
|
||||
%242 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
%243 = OpLoad %float %242
|
||||
%244 = OpFAdd %float %243 %241
|
||||
%245 = OpAccessChain %_ptr_Output_float %FragColor %uint_0
|
||||
OpStore %245 %244
|
||||
%246 = OpAccessChain %_ptr_Input_float %baz %uint_1
|
||||
%247 = OpExtInst %float %1 InterpolateAtSample %246 %int_3
|
||||
%248 = OpAccessChain %_ptr_Output_float %FragColor %uint_1
|
||||
%249 = OpLoad %float %248
|
||||
%250 = OpFAdd %float %249 %247
|
||||
%251 = OpAccessChain %_ptr_Output_float %FragColor %uint_1
|
||||
OpStore %251 %250
|
||||
%252 = OpAccessChain %_ptr_Input_float %baz %uint_1
|
||||
%253 = OpExtInst %float %1 InterpolateAtOffset %252 %30
|
||||
%254 = OpAccessChain %_ptr_Output_float %FragColor %uint_2
|
||||
%255 = OpLoad %float %254
|
||||
%256 = OpFAdd %float %255 %253
|
||||
%257 = OpAccessChain %_ptr_Output_float %FragColor %uint_2
|
||||
OpStore %257 %256
|
||||
%258 = OpAccessChain %_ptr_Input_v2float %a %int_1
|
||||
%259 = OpExtInst %v2float %1 InterpolateAtCentroid %258
|
||||
%260 = OpLoad %v4float %FragColor
|
||||
%261 = OpVectorShuffle %v2float %260 %260 0 1
|
||||
%262 = OpFAdd %v2float %261 %259
|
||||
%263 = OpLoad %v4float %FragColor
|
||||
%264 = OpVectorShuffle %v4float %263 %262 4 5 2 3
|
||||
OpStore %FragColor %264
|
||||
%265 = OpAccessChain %_ptr_Input_v2float %a %int_0
|
||||
%266 = OpExtInst %v2float %1 InterpolateAtSample %265 %int_2
|
||||
%267 = OpLoad %v4float %FragColor
|
||||
%268 = OpVectorShuffle %v2float %267 %267 0 1
|
||||
%269 = OpFAdd %v2float %268 %266
|
||||
%270 = OpLoad %v4float %FragColor
|
||||
%271 = OpVectorShuffle %v4float %270 %269 4 5 2 3
|
||||
OpStore %FragColor %271
|
||||
%272 = OpAccessChain %_ptr_Input_v2float %a %int_1
|
||||
%273 = OpExtInst %v2float %1 InterpolateAtOffset %272 %30
|
||||
%274 = OpLoad %v4float %FragColor
|
||||
%275 = OpVectorShuffle %v2float %274 %274 0 1
|
||||
%276 = OpFAdd %v2float %275 %273
|
||||
%277 = OpLoad %v4float %FragColor
|
||||
%278 = OpVectorShuffle %v4float %277 %276 4 5 2 3
|
||||
OpStore %FragColor %278
|
||||
%279 = OpAccessChain %_ptr_Input_v4float %s %int_2
|
||||
%280 = OpLoad %v4float %279
|
||||
%281 = OpLoad %v4float %FragColor
|
||||
%282 = OpFAdd %v4float %281 %280
|
||||
OpStore %FragColor %282
|
||||
%283 = OpAccessChain %_ptr_Input_v4float %s %int_2
|
||||
%284 = OpExtInst %v4float %1 InterpolateAtCentroid %283
|
||||
%285 = OpVectorShuffle %v2float %284 %284 1 1
|
||||
%286 = OpLoad %v4float %FragColor
|
||||
%287 = OpVectorShuffle %v2float %286 %286 0 1
|
||||
%288 = OpFAdd %v2float %287 %285
|
||||
%289 = OpLoad %v4float %FragColor
|
||||
%290 = OpVectorShuffle %v4float %289 %288 4 5 2 3
|
||||
OpStore %FragColor %290
|
||||
%291 = OpAccessChain %_ptr_Input_v4float %s %int_2
|
||||
%292 = OpExtInst %v4float %1 InterpolateAtSample %291 %int_3
|
||||
%293 = OpVectorShuffle %v2float %292 %292 0 1
|
||||
%294 = OpLoad %v4float %FragColor
|
||||
%295 = OpVectorShuffle %v2float %294 %294 1 2
|
||||
%296 = OpFAdd %v2float %295 %293
|
||||
%297 = OpLoad %v4float %FragColor
|
||||
%298 = OpVectorShuffle %v4float %297 %296 0 4 5 3
|
||||
OpStore %FragColor %298
|
||||
%299 = OpAccessChain %_ptr_Input_v4float %s %int_2
|
||||
%300 = OpExtInst %v4float %1 InterpolateAtOffset %299 %30
|
||||
%301 = OpVectorShuffle %v2float %300 %300 3 0
|
||||
%302 = OpLoad %v4float %FragColor
|
||||
%303 = OpVectorShuffle %v2float %302 %302 2 3
|
||||
%304 = OpFAdd %v2float %303 %301
|
||||
%305 = OpLoad %v4float %FragColor
|
||||
%306 = OpVectorShuffle %v4float %305 %304 0 1 4 5
|
||||
OpStore %FragColor %306
|
||||
%308 = OpAccessChain %_ptr_Input_v4float %s %int_3 %int_0
|
||||
%309 = OpLoad %v4float %308
|
||||
%310 = OpLoad %v4float %FragColor
|
||||
%311 = OpFAdd %v4float %310 %309
|
||||
OpStore %FragColor %311
|
||||
%312 = OpAccessChain %_ptr_Input__arr_v4float_uint_2 %s %int_3
|
||||
%313 = OpAccessChain %_ptr_Input_v4float %312 %int_1
|
||||
%314 = OpExtInst %v4float %1 InterpolateAtCentroid %313
|
||||
%315 = OpLoad %v4float %FragColor
|
||||
%316 = OpFAdd %v4float %315 %314
|
||||
OpStore %FragColor %316
|
||||
%317 = OpAccessChain %_ptr_Input_v4float %s %int_3 %int_0
|
||||
%318 = OpExtInst %v4float %1 InterpolateAtSample %317 %int_2
|
||||
%319 = OpLoad %v4float %FragColor
|
||||
%320 = OpFAdd %v4float %319 %318
|
||||
OpStore %FragColor %320
|
||||
%321 = OpAccessChain %_ptr_Input_v4float %s %int_3 %int_1
|
||||
%322 = OpExtInst %v4float %1 InterpolateAtOffset %321 %30
|
||||
%323 = OpLoad %v4float %FragColor
|
||||
%324 = OpFAdd %v4float %323 %322
|
||||
OpStore %FragColor %324
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -516,6 +516,7 @@ struct SPIRType : IVariant
|
||||
|
||||
// Keep internal types at the end.
|
||||
ControlPointArray,
|
||||
Interpolant,
|
||||
Char
|
||||
};
|
||||
|
||||
@ -1573,6 +1574,13 @@ enum ExtendedDecorations
|
||||
// addition of swizzles to keep the generated code compiling.
|
||||
SPIRVCrossDecorationTessIOOriginalInputTypeID,
|
||||
|
||||
// Apply to any access chain of an interface variable used with pull-model interpolation, where the variable is a
|
||||
// vector but the resulting pointer is a scalar; stores the component index that is to be accessed by the chain.
|
||||
// This is used when emitting calls to interpolation functions on the chain in MSL: in this case, the component
|
||||
// must be applied to the result, since pull-model interpolants in MSL cannot be swizzled directly, but the
|
||||
// results of interpolation can.
|
||||
SPIRVCrossDecorationInterpolantComponentExpr,
|
||||
|
||||
SPIRVCrossDecorationCount
|
||||
};
|
||||
|
||||
|
@ -699,8 +699,31 @@ bool Compiler::InterfaceVariableAccessHandler::handle(Op opcode, const uint32_t
|
||||
{
|
||||
if (length < 5)
|
||||
return false;
|
||||
uint32_t extension_set = args[2];
|
||||
if (compiler.get<SPIRExtension>(extension_set).ext == SPIRExtension::SPV_AMD_shader_explicit_vertex_parameter)
|
||||
auto &extension_set = compiler.get<SPIRExtension>(args[2]);
|
||||
switch (extension_set.ext)
|
||||
{
|
||||
case SPIRExtension::GLSL:
|
||||
{
|
||||
auto op = static_cast<GLSLstd450>(args[3]);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case GLSLstd450InterpolateAtCentroid:
|
||||
case GLSLstd450InterpolateAtSample:
|
||||
case GLSLstd450InterpolateAtOffset:
|
||||
{
|
||||
auto *var = compiler.maybe_get<SPIRVariable>(args[4]);
|
||||
if (var && storage_class_is_interface(var->storage))
|
||||
variables.insert(args[4]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPIRExtension::SPV_AMD_shader_explicit_vertex_parameter:
|
||||
{
|
||||
enum AMDShaderExplicitVertexParameter
|
||||
{
|
||||
@ -722,6 +745,10 @@ bool Compiler::InterfaceVariableAccessHandler::handle(Op opcode, const uint32_t
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
413
spirv_msl.cpp
413
spirv_msl.cpp
@ -169,7 +169,7 @@ void CompilerMSL::build_implicit_builtins()
|
||||
active_input_builtins.get(BuiltInInstanceIndex) || active_input_builtins.get(BuiltInBaseInstance));
|
||||
bool need_sample_mask = msl_options.additional_fixed_sample_mask != 0xffffffff;
|
||||
if (need_subpass_input || need_sample_pos || need_subgroup_mask || need_vertex_params || need_tesc_params ||
|
||||
need_multiview || need_dispatch_base || need_vertex_base_params || need_grid_params ||
|
||||
need_multiview || need_dispatch_base || need_vertex_base_params || need_grid_params || needs_sample_id ||
|
||||
needs_subgroup_invocation_id || needs_subgroup_size || need_sample_mask)
|
||||
{
|
||||
bool has_frag_coord = false;
|
||||
@ -235,7 +235,7 @@ void CompilerMSL::build_implicit_builtins()
|
||||
}
|
||||
}
|
||||
|
||||
if (need_sample_pos && builtin == BuiltInSampleId)
|
||||
if ((need_sample_pos || needs_sample_id) && builtin == BuiltInSampleId)
|
||||
{
|
||||
builtin_sample_id_id = var.self;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInSampleId, var.self);
|
||||
@ -414,7 +414,7 @@ void CompilerMSL::build_implicit_builtins()
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_sample_id && need_sample_pos)
|
||||
if (!has_sample_id && (need_sample_pos || needs_sample_id))
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(2);
|
||||
uint32_t type_ptr_id = offset;
|
||||
@ -1293,6 +1293,8 @@ void CompilerMSL::preprocess_op_codes()
|
||||
needs_subgroup_invocation_id = true;
|
||||
if (preproc.needs_subgroup_size)
|
||||
needs_subgroup_size = true;
|
||||
if (preproc.needs_sample_id)
|
||||
needs_sample_id = true;
|
||||
}
|
||||
|
||||
// Move the Private and Workgroup global variables to the entry function.
|
||||
@ -1464,6 +1466,31 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
||||
break;
|
||||
}
|
||||
|
||||
case OpExtInst:
|
||||
{
|
||||
uint32_t extension_set = ops[2];
|
||||
if (get<SPIRExtension>(extension_set).ext == SPIRExtension::GLSL)
|
||||
{
|
||||
auto op_450 = static_cast<GLSLstd450>(ops[3]);
|
||||
switch (op_450)
|
||||
{
|
||||
case GLSLstd450InterpolateAtCentroid:
|
||||
case GLSLstd450InterpolateAtSample:
|
||||
case GLSLstd450InterpolateAtOffset:
|
||||
{
|
||||
// For these, we really need the stage-in block. It is theoretically possible to pass the
|
||||
// interpolant object, but a) doing so would require us to create an entirely new variable
|
||||
// with Interpolant type, and b) if we have a struct or array, handling all the members and
|
||||
// elements could get unwieldy fast.
|
||||
added_arg_ids.insert(stage_in_var_id);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1695,6 +1722,19 @@ uint32_t CompilerMSL::build_extended_vector_type(uint32_t type_id, uint32_t comp
|
||||
return new_type_id;
|
||||
}
|
||||
|
||||
uint32_t CompilerMSL::build_msl_interpolant_type(uint32_t type_id, bool is_noperspective)
|
||||
{
|
||||
uint32_t new_type_id = ir.increase_bound_by(1);
|
||||
SPIRType &type = set<SPIRType>(new_type_id, get<SPIRType>(type_id));
|
||||
type.basetype = SPIRType::Interpolant;
|
||||
type.parent_type = type_id;
|
||||
// In Metal, the pull-model interpolant type encodes perspective-vs-no-perspective in the type itself.
|
||||
// Add this decoration so we know which argument to pass to the template.
|
||||
if (is_noperspective)
|
||||
set_decoration(new_type_id, DecorationNoPerspective);
|
||||
return new_type_id;
|
||||
}
|
||||
|
||||
void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, const string &ib_var_ref,
|
||||
SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta)
|
||||
{
|
||||
@ -1793,7 +1833,10 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
}
|
||||
}
|
||||
|
||||
ib_type.member_types.push_back(type_id);
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types.push_back(build_msl_interpolant_type(type_id, is_noperspective));
|
||||
else
|
||||
ib_type.member_types.push_back(type_id);
|
||||
|
||||
// Give the member a name
|
||||
string mbr_name = ensure_valid_name(to_expression(var.self), "m");
|
||||
@ -1801,6 +1844,16 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
|
||||
// Update the original variable reference to include the structure reference
|
||||
string qual_var_name = ib_var_ref + "." + mbr_name;
|
||||
// If using pull-model interpolation, need to add a call to the correct interpolation method.
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
{
|
||||
if (is_centroid)
|
||||
qual_var_name += ".interpolate_at_centroid()";
|
||||
else if (is_sample)
|
||||
qual_var_name += join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")");
|
||||
else
|
||||
qual_var_name += ".interpolate_at_center()";
|
||||
}
|
||||
|
||||
if (padded_output || padded_input)
|
||||
{
|
||||
@ -1852,7 +1905,10 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
type_id = get_pointee_type_id(type_id);
|
||||
if (meta.strip_array && is_array(get<SPIRType>(type_id)))
|
||||
type_id = get<SPIRType>(type_id).parent_type;
|
||||
ib_type.member_types[ib_mbr_idx] = type_id;
|
||||
if (pull_model_inputs.count(var.self))
|
||||
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(type_id, is_noperspective);
|
||||
else
|
||||
ib_type.member_types[ib_mbr_idx] = type_id;
|
||||
}
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
|
||||
mark_location_as_used_by_shader(locn, get<SPIRType>(type_id), storage);
|
||||
@ -1888,14 +1944,17 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
}
|
||||
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
|
||||
{
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
// If we have location meta, there is no unique OrigID. We won't need it, since we flatten/unflatten
|
||||
// the variable to stack anyways here.
|
||||
@ -1994,7 +2053,10 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
}
|
||||
}
|
||||
|
||||
ib_type.member_types.push_back(get_pointee_type_id(type_id));
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types.push_back(build_msl_interpolant_type(get_pointee_type_id(type_id), is_noperspective));
|
||||
else
|
||||
ib_type.member_types.push_back(get_pointee_type_id(type_id));
|
||||
|
||||
// Give the member a name
|
||||
string mbr_name = ensure_valid_name(join(to_expression(var.self), "_", i), "m");
|
||||
@ -2008,7 +2070,10 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
{
|
||||
var.basetype = ensure_correct_input_type(var.basetype, locn);
|
||||
uint32_t mbr_type_id = ensure_correct_input_type(usable_type->self, locn);
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective);
|
||||
else
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
}
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
|
||||
mark_location_as_used_by_shader(locn, *usable_type, storage);
|
||||
@ -2032,15 +2097,18 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationIndex, index);
|
||||
}
|
||||
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
|
||||
{
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
|
||||
|
||||
@ -2050,8 +2118,23 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
switch (storage)
|
||||
{
|
||||
case StorageClassInput:
|
||||
entry_func.fixup_hooks_in.push_back(
|
||||
[=, &var]() { statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";"); });
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
if (pull_model_inputs.count(var.self))
|
||||
{
|
||||
string lerp_call;
|
||||
if (is_centroid)
|
||||
lerp_call = ".interpolate_at_centroid()";
|
||||
else if (is_sample)
|
||||
lerp_call = join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")");
|
||||
else
|
||||
lerp_call = ".interpolate_at_center()";
|
||||
statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, lerp_call, ";");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(to_name(var.self), "[", i, "] = ", ib_var_ref, ".", mbr_name, ";");
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case StorageClassOutput:
|
||||
@ -2175,7 +2258,10 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
|
||||
{
|
||||
// Add a reference to the variable type to the interface struct.
|
||||
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
|
||||
ib_type.member_types.push_back(usable_type->self);
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types.push_back(build_msl_interpolant_type(usable_type->self, is_noperspective));
|
||||
else
|
||||
ib_type.member_types.push_back(usable_type->self);
|
||||
|
||||
// Give the member a name
|
||||
string mbr_name = ensure_valid_name(join(to_qualified_member_name(var_type, mbr_idx), "_", i), "m");
|
||||
@ -2209,15 +2295,18 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
|
||||
if (has_member_decoration(var_type.self, mbr_idx, DecorationComponent))
|
||||
SPIRV_CROSS_THROW("DecorationComponent on matrices and arrays make little sense.");
|
||||
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
|
||||
{
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx);
|
||||
@ -2229,8 +2318,23 @@ void CompilerMSL::add_composite_member_variable_to_interface_block(StorageClass
|
||||
{
|
||||
case StorageClassInput:
|
||||
entry_func.fixup_hooks_in.push_back([=, &var, &var_type]() {
|
||||
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
|
||||
".", mbr_name, ";");
|
||||
if (pull_model_inputs.count(var.self))
|
||||
{
|
||||
string lerp_call;
|
||||
if (is_centroid)
|
||||
lerp_call = ".interpolate_at_centroid()";
|
||||
else if (is_sample)
|
||||
lerp_call = join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")");
|
||||
else
|
||||
lerp_call = ".interpolate_at_center()";
|
||||
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
|
||||
".", mbr_name, lerp_call, ";");
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(to_name(var.self), ".", to_member_name(var_type, mbr_idx), "[", i, "] = ", ib_var_ref,
|
||||
".", mbr_name, ";");
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
@ -2279,7 +2383,10 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
|
||||
mbr_type_id = ensure_correct_builtin_type(mbr_type_id, builtin);
|
||||
var_type.member_types[mbr_idx] = mbr_type_id;
|
||||
ib_type.member_types.push_back(mbr_type_id);
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types.push_back(build_msl_interpolant_type(mbr_type_id, is_noperspective));
|
||||
else
|
||||
ib_type.member_types.push_back(mbr_type_id);
|
||||
|
||||
// Give the member a name
|
||||
string mbr_name = ensure_valid_name(to_qualified_member_name(var_type, mbr_idx), "m");
|
||||
@ -2287,6 +2394,16 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
|
||||
// Update the original variable reference to include the structure reference
|
||||
string qual_var_name = ib_var_ref + "." + mbr_name;
|
||||
// If using pull-model interpolation, need to add a call to the correct interpolation method.
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
{
|
||||
if (is_centroid)
|
||||
qual_var_name += ".interpolate_at_centroid()";
|
||||
else if (is_sample)
|
||||
qual_var_name += join(".interpolate_at_sample(", to_expression(builtin_sample_id_id), ")");
|
||||
else
|
||||
qual_var_name += ".interpolate_at_center()";
|
||||
}
|
||||
|
||||
if (is_builtin && !meta.strip_array)
|
||||
{
|
||||
@ -2324,7 +2441,10 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
{
|
||||
mbr_type_id = ensure_correct_input_type(mbr_type_id, locn);
|
||||
var_type.member_types[mbr_idx] = mbr_type_id;
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective);
|
||||
else
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
}
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
|
||||
mark_location_as_used_by_shader(locn, get<SPIRType>(mbr_type_id), storage);
|
||||
@ -2338,7 +2458,10 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
{
|
||||
mbr_type_id = ensure_correct_input_type(mbr_type_id, locn);
|
||||
var_type.member_types[mbr_idx] = mbr_type_id;
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
if (storage == StorageClassInput && pull_model_inputs.count(var.self))
|
||||
ib_type.member_types[ib_mbr_idx] = build_msl_interpolant_type(mbr_type_id, is_noperspective);
|
||||
else
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
}
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
|
||||
mark_location_as_used_by_shader(locn, get<SPIRType>(mbr_type_id), storage);
|
||||
@ -2368,15 +2491,18 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
qual_pos_var_name = qual_var_name;
|
||||
}
|
||||
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
|
||||
{
|
||||
// Copy interpolation decorations if needed
|
||||
if (is_flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (is_noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (is_centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (is_sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceMemberIndex, mbr_idx);
|
||||
@ -2607,11 +2733,13 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
|
||||
// for per-vertex variables in a tessellation control shader.
|
||||
void CompilerMSL::fix_up_interface_member_indices(StorageClass storage, uint32_t ib_type_id)
|
||||
{
|
||||
// Only needed for tessellation shaders.
|
||||
// Only needed for tessellation shaders and pull-model interpolants.
|
||||
// Need to redirect interface indices back to variables themselves.
|
||||
// For structs, each member of the struct need a separate instance.
|
||||
if (get_execution_model() != ExecutionModelTessellationControl &&
|
||||
!(get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput))
|
||||
!(get_execution_model() == ExecutionModelTessellationEvaluation && storage == StorageClassInput) &&
|
||||
!(get_execution_model() == ExecutionModelFragment && storage == StorageClassInput &&
|
||||
!pull_model_inputs.empty()))
|
||||
return;
|
||||
|
||||
auto mbr_cnt = uint32_t(ir.meta[ib_type_id].members.size());
|
||||
@ -6549,6 +6677,61 @@ void CompilerMSL::prepare_access_chain_for_scalar_access(std::string &expr, cons
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the interface member index for an access chain to a pull-model interpolant.
|
||||
void CompilerMSL::fix_up_interpolant_access_chain(const uint32_t *ops, uint32_t length)
|
||||
{
|
||||
auto *var = maybe_get_backing_variable(ops[2]);
|
||||
if (!var || !pull_model_inputs.count(var->self))
|
||||
return;
|
||||
// Get the base index.
|
||||
uint32_t interface_index;
|
||||
auto &var_type = get_variable_data_type(*var);
|
||||
auto &result_type = get<SPIRType>(ops[0]);
|
||||
auto *type = &var_type;
|
||||
if (has_extended_decoration(ops[2], SPIRVCrossDecorationInterfaceMemberIndex))
|
||||
{
|
||||
interface_index = get_extended_decoration(ops[2], SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume an access chain into a struct variable.
|
||||
assert(var_type.basetype == SPIRType::Struct);
|
||||
auto &c = get<SPIRConstant>(ops[3 + var_type.array.size()]);
|
||||
interface_index = get_extended_member_decoration(var->self, c.scalar(),
|
||||
SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
}
|
||||
// Accumulate indices. We'll have to skip over the one for the struct, if present, because we already accounted
|
||||
// for that getting the base index.
|
||||
for (uint32_t i = 3; i < length; ++i)
|
||||
{
|
||||
if (is_vector(*type) && is_scalar(result_type))
|
||||
{
|
||||
// We don't want to combine the next index. Actually, we need to save it
|
||||
// so we know to apply a swizzle to the result of the interpolation.
|
||||
set_extended_decoration(ops[1], SPIRVCrossDecorationInterpolantComponentExpr, ops[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
auto *c = maybe_get<SPIRConstant>(ops[i]);
|
||||
if (!c || c->specialization)
|
||||
SPIRV_CROSS_THROW("Trying to dynamically index into an array interface variable using pull-model "
|
||||
"interpolation. This is currently unsupported.");
|
||||
|
||||
if (type->parent_type)
|
||||
type = &get<SPIRType>(type->parent_type);
|
||||
else if (type->basetype == SPIRType::Struct)
|
||||
type = &get<SPIRType>(type->member_types[c->scalar()]);
|
||||
|
||||
if (!has_extended_decoration(ops[2], SPIRVCrossDecorationInterfaceMemberIndex) &&
|
||||
i - 3 == var_type.array.size())
|
||||
continue;
|
||||
|
||||
interface_index += c->scalar();
|
||||
}
|
||||
// Save this to the access chain itself so we can recover it later when calling an interpolation function.
|
||||
set_extended_decoration(ops[1], SPIRVCrossDecorationInterfaceMemberIndex, interface_index);
|
||||
}
|
||||
|
||||
// Override for MSL-specific syntax instructions
|
||||
void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
{
|
||||
@ -7144,6 +7327,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
||||
}
|
||||
else
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
fix_up_interpolant_access_chain(ops, instruction.length);
|
||||
break;
|
||||
|
||||
case OpStore:
|
||||
@ -7903,10 +8087,70 @@ void CompilerMSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
|
||||
emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "precise::clamp");
|
||||
break;
|
||||
|
||||
// TODO:
|
||||
// GLSLstd450InterpolateAtCentroid (centroid_no_perspective qualifier)
|
||||
// GLSLstd450InterpolateAtSample (sample_no_perspective qualifier)
|
||||
// GLSLstd450InterpolateAtOffset
|
||||
case GLSLstd450InterpolateAtCentroid:
|
||||
{
|
||||
// We can't just emit the expression normally, because the qualified name contains a call to the default
|
||||
// interpolate method, or refers to a local variable. We saved the interface index we need; use it to construct
|
||||
// the base for the method call.
|
||||
uint32_t interface_index = get_extended_decoration(args[0], SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
string component;
|
||||
if (has_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr))
|
||||
{
|
||||
uint32_t index_expr = get_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr);
|
||||
auto *c = maybe_get<SPIRConstant>(index_expr);
|
||||
if (!c || c->specialization)
|
||||
component = join("[", to_expression(index_expr), "]");
|
||||
else
|
||||
component = join(".", index_to_swizzle(c->scalar()));
|
||||
}
|
||||
emit_op(result_type, id,
|
||||
join(to_name(stage_in_var_id), ".", to_member_name(get_stage_in_struct_type(), interface_index),
|
||||
".interpolate_at_centroid()", component), should_forward(args[0]));
|
||||
break;
|
||||
}
|
||||
|
||||
case GLSLstd450InterpolateAtSample:
|
||||
{
|
||||
uint32_t interface_index = get_extended_decoration(args[0], SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
string component;
|
||||
if (has_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr))
|
||||
{
|
||||
uint32_t index_expr = get_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr);
|
||||
auto *c = maybe_get<SPIRConstant>(index_expr);
|
||||
if (!c || c->specialization)
|
||||
component = join("[", to_expression(index_expr), "]");
|
||||
else
|
||||
component = join(".", index_to_swizzle(c->scalar()));
|
||||
}
|
||||
emit_op(result_type, id,
|
||||
join(to_name(stage_in_var_id), ".", to_member_name(get_stage_in_struct_type(), interface_index),
|
||||
".interpolate_at_sample(", to_expression(args[1]), ")", component),
|
||||
should_forward(args[0]) && should_forward(args[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
case GLSLstd450InterpolateAtOffset:
|
||||
{
|
||||
uint32_t interface_index = get_extended_decoration(args[0], SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
string component;
|
||||
if (has_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr))
|
||||
{
|
||||
uint32_t index_expr = get_extended_decoration(args[0], SPIRVCrossDecorationInterpolantComponentExpr);
|
||||
auto *c = maybe_get<SPIRConstant>(index_expr);
|
||||
if (!c || c->specialization)
|
||||
component = join("[", to_expression(index_expr), "]");
|
||||
else
|
||||
component = join(".", index_to_swizzle(c->scalar()));
|
||||
}
|
||||
// Like Direct3D, Metal puts the (0, 0) at the upper-left corner, not the center as SPIR-V and GLSL do.
|
||||
// Offset the offset by (1/2 - 1/16), or 0.4375, to compensate for this.
|
||||
// It has to be (1/2 - 1/16) and not 1/2, or several CTS tests subtly break on Intel.
|
||||
emit_op(result_type, id,
|
||||
join(to_name(stage_in_var_id), ".", to_member_name(get_stage_in_struct_type(), interface_index),
|
||||
".interpolate_at_offset(", to_expression(args[1]), " + 0.4375)", component),
|
||||
should_forward(args[0]) && should_forward(args[1]));
|
||||
break;
|
||||
}
|
||||
|
||||
case GLSLstd450Distance:
|
||||
// MSL does not support scalar versions here.
|
||||
@ -9951,6 +10195,8 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id, bo
|
||||
if (get_execution_model() == ExecutionModelTessellationControl && var &&
|
||||
var->basevariable == stage_in_ptr_var_id)
|
||||
addr_space = msl_options.multi_patch_workgroup ? "constant" : "threadgroup";
|
||||
if (get_execution_model() == ExecutionModelFragment && var && var->basevariable == stage_in_var_id)
|
||||
addr_space = "thread";
|
||||
break;
|
||||
|
||||
case StorageClassOutput:
|
||||
@ -11255,7 +11501,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
|
||||
decl += ")";
|
||||
decl += type_to_array_glsl(type);
|
||||
}
|
||||
else if (!opaque_handle)
|
||||
else if (!opaque_handle && (!pull_model_inputs.count(var.basevariable) || type.basetype == SPIRType::Struct))
|
||||
{
|
||||
// If this is going to be a reference to a variable pointer, the address space
|
||||
// for the reference has to go before the '&', but after the '*'.
|
||||
@ -11729,6 +11975,10 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
||||
|
||||
case SPIRType::ControlPointArray:
|
||||
return join("patch_control_point<", type_to_glsl(get<SPIRType>(type.parent_type), id), ">");
|
||||
|
||||
case SPIRType::Interpolant:
|
||||
return join("interpolant<", type_to_glsl(get<SPIRType>(type.parent_type), id), ", interpolation::",
|
||||
has_decoration(type.self, DecorationNoPerspective) ? "no_perspective" : "perspective", ">");
|
||||
|
||||
// Scalars
|
||||
case SPIRType::Boolean:
|
||||
@ -13310,6 +13560,55 @@ bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, ui
|
||||
break;
|
||||
}
|
||||
|
||||
case OpExtInst:
|
||||
{
|
||||
uint32_t extension_set = args[2];
|
||||
if (compiler.get<SPIRExtension>(extension_set).ext == SPIRExtension::GLSL)
|
||||
{
|
||||
auto op_450 = static_cast<GLSLstd450>(args[3]);
|
||||
switch (op_450)
|
||||
{
|
||||
case GLSLstd450InterpolateAtCentroid:
|
||||
case GLSLstd450InterpolateAtSample:
|
||||
case GLSLstd450InterpolateAtOffset:
|
||||
{
|
||||
if (!compiler.msl_options.supports_msl_version(2, 3))
|
||||
SPIRV_CROSS_THROW("Pull-model interpolation requires MSL 2.3.");
|
||||
// Fragment varyings used with pull-model interpolation need special handling,
|
||||
// due to the way pull-model interpolation works in Metal.
|
||||
auto *var = compiler.maybe_get_backing_variable(args[4]);
|
||||
if (var)
|
||||
{
|
||||
compiler.pull_model_inputs.insert(var->self);
|
||||
auto &var_type = compiler.get_variable_element_type(*var);
|
||||
// In addition, if this variable has a 'Sample' decoration, we need the sample ID
|
||||
// in order to do default interpolation.
|
||||
if (compiler.has_decoration(var->self, DecorationSample))
|
||||
{
|
||||
needs_sample_id = true;
|
||||
}
|
||||
else if (var_type.basetype == SPIRType::Struct)
|
||||
{
|
||||
// Now we need to check each member and see if it has this decoration.
|
||||
for (uint32_t i = 0; i < var_type.member_types.size(); ++i)
|
||||
{
|
||||
if (compiler.has_member_decoration(var_type.self, i, DecorationSample))
|
||||
{
|
||||
needs_sample_id = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -869,6 +869,7 @@ protected:
|
||||
|
||||
void prepare_access_chain_for_scalar_access(std::string &expr, const SPIRType &type, spv::StorageClass storage,
|
||||
bool &is_packed) override;
|
||||
void fix_up_interpolant_access_chain(const uint32_t *ops, uint32_t length);
|
||||
bool emit_tessellation_access_chain(const uint32_t *ops, uint32_t length);
|
||||
bool emit_tessellation_io_load(uint32_t result_type, uint32_t id, uint32_t ptr);
|
||||
bool is_out_of_bounds_tessellation_level(uint32_t id_lhs);
|
||||
@ -928,6 +929,7 @@ protected:
|
||||
bool added_builtin_tess_level = false;
|
||||
bool needs_subgroup_invocation_id = false;
|
||||
bool needs_subgroup_size = false;
|
||||
bool needs_sample_id = false;
|
||||
std::string qual_pos_var_name;
|
||||
std::string stage_in_var_name = "in";
|
||||
std::string stage_out_var_name = "out";
|
||||
@ -953,6 +955,7 @@ protected:
|
||||
std::unordered_set<uint32_t> buffers_requiring_array_length;
|
||||
SmallVector<uint32_t> buffer_arrays;
|
||||
std::unordered_set<uint32_t> atomic_image_vars; // Emulate texture2D atomic operations
|
||||
std::unordered_set<uint32_t> pull_model_inputs;
|
||||
|
||||
// Must be ordered since array is in a specific order.
|
||||
std::map<SetBindingPair, std::pair<uint32_t, uint32_t>> buffers_requiring_dynamic_offset;
|
||||
@ -971,6 +974,7 @@ protected:
|
||||
uint32_t get_target_components_for_fragment_location(uint32_t location) const;
|
||||
uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components,
|
||||
SPIRType::BaseType basetype = SPIRType::Unknown);
|
||||
uint32_t build_msl_interpolant_type(uint32_t type_id, bool is_noperspective);
|
||||
|
||||
bool suppress_missing_prototypes = false;
|
||||
|
||||
@ -1000,6 +1004,7 @@ protected:
|
||||
bool uses_resource_write = false;
|
||||
bool needs_subgroup_invocation_id = false;
|
||||
bool needs_subgroup_size = false;
|
||||
bool needs_sample_id = false;
|
||||
};
|
||||
|
||||
// OpcodeHandler that scans for uses of sampled images
|
||||
|
Loading…
Reference in New Issue
Block a user