MSL: Adjust FragCoord for sample-rate shading.
In Metal, the `[[position]]` input to a fragment shader remains at fragment center, even at sample rate, like OpenGL and Direct3D. In Vulkan, however, when the fragment shader runs at sample rate, the `FragCoord` builtin moves to the sample position in the framebuffer, instead of the fragment center. To account for this difference, adjust the `FragCoord`, if present, by the sample position. The -0.5 offset is because the fragment center is at (0.5, 0.5). Also, add an option to force sample-rate shading in a fragment shader. Since Metal has no explicit control for this, this is done by adding a dummy `[[sample_id]]` which is otherwise unused, if none is already present. This is intended to be used from e.g. MoltenVK when a pipeline's `minSampleShading` value is nonzero. Instead of checking if any `Input` variables have `Sample` interpolation, I've elected to check that the `SampleRateShading` capability is present. Since `SampleId`, `SamplePosition`, and the `Sample` interpolation decoration require this cap, this should be equivalent for any valid SPIR-V module. If this isn't acceptable, let me know.
This commit is contained in:
Родитель
782916a797
Коммит
fd738e3387
|
@ -323,7 +323,7 @@ if (SPIRV_CROSS_STATIC)
|
|||
endif()
|
||||
|
||||
set(spirv-cross-abi-major 0)
|
||||
set(spirv-cross-abi-minor 43)
|
||||
set(spirv-cross-abi-minor 44)
|
||||
set(spirv-cross-abi-patch 0)
|
||||
|
||||
if (SPIRV_CROSS_SHARED)
|
||||
|
|
7
main.cpp
7
main.cpp
|
@ -569,6 +569,7 @@ struct CLIArguments
|
|||
bool msl_ios_use_simdgroup_functions = false;
|
||||
bool msl_emulate_subgroups = false;
|
||||
uint32_t msl_fixed_subgroup_size = 0;
|
||||
bool msl_force_sample_rate_shading = false;
|
||||
bool glsl_emit_push_constant_as_ubo = false;
|
||||
bool glsl_emit_ubo_as_plain_uniforms = false;
|
||||
bool glsl_force_flattened_io_blocks = false;
|
||||
|
@ -789,7 +790,9 @@ static void print_help_msl()
|
|||
"\t\tIntended for Vulkan Portability implementations where Metal support for SIMD-groups is insufficient for true subgroups.\n"
|
||||
"\t[--msl-fixed-subgroup-size <size>]:\n\t\tAssign a constant <size> to the SubgroupSize builtin.\n"
|
||||
"\t\tIntended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled.\n"
|
||||
"\t\tIf 0, assume variable subgroup size as actually exposed by Metal.\n");
|
||||
"\t\tIf 0, assume variable subgroup size as actually exposed by Metal.\n"
|
||||
"\t[--msl-force-sample-rate-shading]:\n\t\tForce fragment shaders to run per sample.\n"
|
||||
"\t\tThis adds a [[sample_id]] parameter if none is already present.\n");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
@ -1034,6 +1037,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
|||
msl_opts.ios_use_simdgroup_functions = args.msl_ios_use_simdgroup_functions;
|
||||
msl_opts.emulate_subgroups = args.msl_emulate_subgroups;
|
||||
msl_opts.fixed_subgroup_size = args.msl_fixed_subgroup_size;
|
||||
msl_opts.force_sample_rate_shading = args.msl_force_sample_rate_shading;
|
||||
msl_comp->set_msl_options(msl_opts);
|
||||
for (auto &v : args.msl_discrete_descriptor_sets)
|
||||
msl_comp->add_discrete_descriptor_set(v);
|
||||
|
@ -1466,6 +1470,7 @@ static int main_inner(int argc, char *argv[])
|
|||
cbs.add("--msl-emulate-subgroups", [&args](CLIParser &) { args.msl_emulate_subgroups = true; });
|
||||
cbs.add("--msl-fixed-subgroup-size",
|
||||
[&args](CLIParser &parser) { args.msl_fixed_subgroup_size = parser.next_uint(); });
|
||||
cbs.add("--msl-force-sample-rate-shading", [&args](CLIParser &) { args.msl_force_sample_rate_shading = true; });
|
||||
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
|
||||
cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
|
||||
auto old_name = parser.next_string();
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vColor [[user(locn0)]];
|
||||
float2 vTex [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uTex [[texture(0)]], sampler uTexSmplr [[sampler(0)]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = in.vColor * uTex.sample(uTexSmplr, in.vTex);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ struct main0_out
|
|||
fragment main0_out main0(texture2d_ms_array<float> uSubpass0 [[texture(0)]], texture2d_ms_array<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]], uint gl_Layer [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), gl_Layer, 1) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_Layer, 2)) + uSubpass0.read(uint2(gl_FragCoord.xy), gl_Layer, gl_SampleID);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ struct main0_out
|
|||
fragment main0_out main0(texture2d_ms<float> uSubpass0 [[texture(0)]], texture2d_ms<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), 1) + uSubpass1.read(uint2(gl_FragCoord.xy), 2)) + uSubpass0.read(uint2(gl_FragCoord.xy), gl_SampleID);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ struct main0_out
|
|||
fragment main0_out main0(constant uint* spvViewMask [[buffer(24)]], texture2d_ms_array<float> uSubpass0 [[texture(0)]], texture2d_ms_array<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]], uint gl_ViewIndex [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
gl_ViewIndex += spvViewMask[0];
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), gl_ViewIndex, 1) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_ViewIndex, 2)) + uSubpass0.read(uint2(gl_FragCoord.xy), gl_ViewIndex, gl_SampleID);
|
||||
return out;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d_array<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float3 _28 = float3(gl_FragCoord.xy, float(gl_SampleID));
|
||||
out.FragColor = tex.sample(texSmplr, _28.xy, uint(round(_28.z)));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float foo [[user(locn0), sample_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], texture2d_array<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float3 _26 = float3(gl_FragCoord.xy, in.foo);
|
||||
out.FragColor = tex.sample(texSmplr, _26.xy, uint(round(_26.z)));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float2 gl_SamplePosition = get_sample_position(gl_SampleID);
|
||||
out.FragColor = tex.sample(texSmplr, (gl_FragCoord.xy - gl_SamplePosition));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = tex.sample(texSmplr, gl_FragCoord.xy);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -197,9 +197,10 @@ struct main0_out
|
|||
float4 out_var_SV_Target0 [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]])
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float4 _67 = _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData;
|
||||
float _68 = _67.w;
|
||||
float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0);
|
||||
|
|
|
@ -197,9 +197,10 @@ struct main0_out
|
|||
float4 out_var_SV_Target0 [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]])
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float4 _67 = _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData;
|
||||
float _68 = _67.w;
|
||||
float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vColor [[user(locn0)]];
|
||||
float2 vTex [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> uTex [[texture(0)]], sampler uTexSmplr [[sampler(0)]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = in.vColor * uTex.sample(uTexSmplr, in.vTex);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ float4 load_subpasses(thread const texture2d_ms_array<float> uInput, thread uint
|
|||
fragment main0_out main0(texture2d_ms_array<float> uSubpass0 [[texture(0)]], texture2d_ms_array<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]], uint gl_Layer [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), gl_Layer, 1) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_Layer, 2)) + load_subpasses(uSubpass0, gl_SampleID, gl_FragCoord, gl_Layer);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ float4 load_subpasses(thread const texture2d_ms<float> uInput, thread uint& gl_S
|
|||
fragment main0_out main0(texture2d_ms<float> uSubpass0 [[texture(0)]], texture2d_ms<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), 1) + uSubpass1.read(uint2(gl_FragCoord.xy), 2)) + load_subpasses(uSubpass0, gl_SampleID, gl_FragCoord);
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ float4 load_subpasses(thread const texture2d_ms_array<float> uInput, thread uint
|
|||
fragment main0_out main0(constant uint* spvViewMask [[buffer(24)]], texture2d_ms_array<float> uSubpass0 [[texture(0)]], texture2d_ms_array<float> uSubpass1 [[texture(1)]], uint gl_SampleID [[sample_id]], float4 gl_FragCoord [[position]], uint gl_ViewIndex [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
gl_ViewIndex += spvViewMask[0];
|
||||
out.FragColor = (uSubpass0.read(uint2(gl_FragCoord.xy), gl_ViewIndex, 1) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_ViewIndex, 2)) + load_subpasses(uSubpass0, gl_SampleID, gl_FragCoord, gl_ViewIndex);
|
||||
return out;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d_array<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float3 _28 = float3(gl_FragCoord.xy, float(gl_SampleID));
|
||||
out.FragColor = tex.sample(texSmplr, _28.xy, uint(round(_28.z)));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float foo [[user(locn0), sample_perspective]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], texture2d_array<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float3 _26 = float3(gl_FragCoord.xy, in.foo);
|
||||
out.FragColor = tex.sample(texSmplr, _26.xy, uint(round(_26.z)));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float2 gl_SamplePosition = get_sample_position(gl_SampleID);
|
||||
out.FragColor = tex.sample(texSmplr, (gl_FragCoord.xy - gl_SamplePosition));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
out.FragColor = tex.sample(texSmplr, gl_FragCoord.xy);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -197,9 +197,10 @@ struct main0_out
|
|||
float4 out_var_SV_Target0 [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]])
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float4 _67 = _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData;
|
||||
float _68 = _67.w;
|
||||
float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0);
|
||||
|
|
|
@ -197,9 +197,10 @@ struct main0_out
|
|||
float4 out_var_SV_Target0 [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]])
|
||||
fragment main0_out main0(constant type_View& View [[buffer(0)]], constant type_Globals& _Globals [[buffer(1)]], float4 _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData [[color(0)]], texture2d<float> ShadowDepthTexture [[texture(0)]], sampler ShadowDepthTextureSampler [[sampler(0)]], float4 gl_FragCoord [[position]], uint gl_SampleID [[sample_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_FragCoord.xy += get_sample_position(gl_SampleID) - 0.5;
|
||||
float4 _67 = _RESERVED_IDENTIFIER_FIXUP_gl_LastFragData;
|
||||
float _68 = _67.w;
|
||||
float4 _82 = _Globals.ScreenToShadowMatrix * float4((((gl_FragCoord.xy * View.View_BufferSizeAndInvSize.zw) - View.View_ScreenPositionScaleBias.wz) / View.View_ScreenPositionScaleBias.xy) * float2(_68), _68, 1.0);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) in vec4 vColor;
|
||||
layout(location = 1) in vec2 vTex;
|
||||
layout(binding = 0) uniform sampler2D uTex;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = vColor * texture(uTex, vTex);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2DArray tex;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, vec3(gl_FragCoord.xy, float(gl_SampleID)));
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2DArray tex;
|
||||
|
||||
layout(location = 0) sample in float foo;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, vec3(gl_FragCoord.xy, foo));
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, gl_FragCoord.xy - gl_SamplePosition);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, gl_FragCoord.xy);
|
||||
}
|
|
@ -690,6 +690,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
|
|||
case SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE:
|
||||
options->msl.fixed_subgroup_size = value;
|
||||
break;
|
||||
|
||||
case SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING:
|
||||
options->msl.force_sample_rate_shading = value != 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
|
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
/* Bumped if ABI or API breaks backwards compatibility. */
|
||||
#define SPVC_C_API_VERSION_MAJOR 0
|
||||
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
|
||||
#define SPVC_C_API_VERSION_MINOR 43
|
||||
#define SPVC_C_API_VERSION_MINOR 44
|
||||
/* Bumped if internal implementation details change. */
|
||||
#define SPVC_C_API_VERSION_PATCH 0
|
||||
|
||||
|
@ -650,6 +650,7 @@ typedef enum spvc_compiler_option
|
|||
SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS = 72 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS = 73 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE = 74 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING = 75 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
|
||||
} spvc_compiler_option;
|
||||
|
|
|
@ -1354,7 +1354,12 @@ void CompilerMSL::preprocess_op_codes()
|
|||
needs_subgroup_invocation_id = true;
|
||||
if (preproc.needs_subgroup_size)
|
||||
needs_subgroup_size = true;
|
||||
if (preproc.needs_sample_id)
|
||||
// build_implicit_builtins() hasn't run yet, and in fact, this needs to execute
|
||||
// before then so that gl_SampleID will get added; so we also need to check if
|
||||
// that function would add gl_FragCoord.
|
||||
if (preproc.needs_sample_id || msl_options.force_sample_rate_shading ||
|
||||
(is_sample_rate() && (active_input_builtins.get(BuiltInFragCoord) ||
|
||||
(need_subpass_input && !msl_options.use_framebuffer_fetch_subpasses))))
|
||||
needs_sample_id = true;
|
||||
}
|
||||
|
||||
|
@ -10495,6 +10500,16 @@ bool CompilerMSL::is_direct_input_builtin(BuiltIn bi_type)
|
|||
}
|
||||
}
|
||||
|
||||
// Returns true if this is a fragment shader that runs per sample, and false otherwise.
|
||||
bool CompilerMSL::is_sample_rate() const
|
||||
{
|
||||
auto &caps = get_declared_capabilities();
|
||||
return get_execution_model() == ExecutionModelFragment &&
|
||||
(msl_options.force_sample_rate_shading ||
|
||||
std::find(caps.begin(), caps.end(), CapabilitySampleRateShading) != caps.end() ||
|
||||
(msl_options.use_framebuffer_fetch_subpasses && need_subpass_input));
|
||||
}
|
||||
|
||||
void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
||||
{
|
||||
// Builtin variables
|
||||
|
@ -11047,6 +11062,15 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
|
|||
to_expression(builtin_sample_id_id), ");");
|
||||
});
|
||||
break;
|
||||
case BuiltInFragCoord:
|
||||
if (is_sample_rate())
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
statement(to_expression(var_id), ".xy += get_sample_position(",
|
||||
to_expression(builtin_sample_id_id), ") - 0.5;");
|
||||
});
|
||||
}
|
||||
break;
|
||||
case BuiltInHelperInvocation:
|
||||
if (msl_options.is_ios() && !msl_options.supports_msl_version(2, 3))
|
||||
SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.3 on iOS.");
|
||||
|
|
|
@ -401,6 +401,11 @@ public:
|
|||
// different shaders for these three scenarios.
|
||||
IndexType vertex_index_type = IndexType::None;
|
||||
|
||||
// If set, a dummy [[sample_id]] input is added to a fragment shader if none is present.
|
||||
// This will force the shader to run at sample rate, assuming Metal does not optimize
|
||||
// the extra threads away.
|
||||
bool force_sample_rate_shading = false;
|
||||
|
||||
bool is_ios() const
|
||||
{
|
||||
return platform == iOS;
|
||||
|
@ -798,6 +803,7 @@ protected:
|
|||
std::string to_sampler_expression(uint32_t id);
|
||||
std::string to_swizzle_expression(uint32_t id);
|
||||
std::string to_buffer_size_expression(uint32_t id);
|
||||
bool is_sample_rate() const;
|
||||
bool is_direct_input_builtin(spv::BuiltIn builtin);
|
||||
std::string builtin_qualifier(spv::BuiltIn builtin);
|
||||
std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0);
|
||||
|
|
|
@ -316,6 +316,8 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths):
|
|||
# Arbitrary for testing purposes.
|
||||
msl_args.append('--msl-fixed-subgroup-size')
|
||||
msl_args.append('32')
|
||||
if '.force-sample.' in shader:
|
||||
msl_args.append('--msl-force-sample-rate-shading')
|
||||
|
||||
subprocess.check_call(msl_args)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче