MSL: Support layered input attachments.
These need to use arrayed texture types, or Metal will complain when binding the resource. The target layer is addressed relative to the Layer output by the vertex pipeline, or to the ViewIndex if in a multiview pipeline. Unlike with the s/t coordinates, Vulkan does not forbid non-zero layer coordinates here, though this cannot be expressed in Vulkan GLSL. Supporting 3D textures will require additional work. Part of the problem is that Metal does not allow texture views to subset a 3D texture, so we need some way to pass the base depth to the shader.
This commit is contained in:
parent
c7507e39d4
commit
4cf840ee7b
@ -323,7 +323,7 @@ if (SPIRV_CROSS_STATIC)
|
||||
endif()
|
||||
|
||||
set(spirv-cross-abi-major 0)
|
||||
set(spirv-cross-abi-minor 38)
|
||||
set(spirv-cross-abi-minor 39)
|
||||
set(spirv-cross-abi-patch 0)
|
||||
|
||||
if (SPIRV_CROSS_SHARED)
|
||||
|
7
main.cpp
7
main.cpp
@ -562,6 +562,7 @@ struct CLIArguments
|
||||
bool msl_multi_patch_workgroup = false;
|
||||
bool msl_vertex_for_tessellation = false;
|
||||
uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
|
||||
bool msl_arrayed_subpass_input = false;
|
||||
bool glsl_emit_push_constant_as_ubo = false;
|
||||
bool glsl_emit_ubo_as_plain_uniforms = false;
|
||||
bool glsl_force_flattened_io_blocks = false;
|
||||
@ -765,7 +766,9 @@ static void print_help_msl()
|
||||
"\t[--msl-vertex-for-tessellation]:\n\t\tWhen handling a vertex shader, marks it as one that will be used with a new-style tessellation control shader.\n"
|
||||
"\t\tThe vertex shader is output to MSL as a compute kernel which outputs vertices to the buffer in the order they are received, rather than in index order as with --msl-capture-output normally.\n"
|
||||
"\t[--msl-additional-fixed-sample-mask <mask>]:\n"
|
||||
"\t\tSet an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two.\n");
|
||||
"\t\tSet an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two.\n"
|
||||
"\t[--msl-arrayed-subpass-input]:\n\t\tAssume that images of dimension SubpassData have multiple layers. Layered input attachments are accessed relative to BuiltInLayer.\n"
|
||||
"\t\tThis option has no effect if multiview is also enabled.\n");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@ -1003,6 +1006,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
||||
msl_opts.multi_patch_workgroup = args.msl_multi_patch_workgroup;
|
||||
msl_opts.vertex_for_tessellation = args.msl_vertex_for_tessellation;
|
||||
msl_opts.additional_fixed_sample_mask = args.msl_additional_fixed_sample_mask;
|
||||
msl_opts.arrayed_subpass_input = args.msl_arrayed_subpass_input;
|
||||
msl_comp->set_msl_options(msl_opts);
|
||||
for (auto &v : args.msl_discrete_descriptor_sets)
|
||||
msl_comp->add_discrete_descriptor_set(v);
|
||||
@ -1422,6 +1426,7 @@ static int main_inner(int argc, char *argv[])
|
||||
cbs.add("--msl-vertex-for-tessellation", [&args](CLIParser &) { args.msl_vertex_for_tessellation = true; });
|
||||
cbs.add("--msl-additional-fixed-sample-mask",
|
||||
[&args](CLIParser &parser) { args.msl_additional_fixed_sample_mask = parser.next_hex_uint(); });
|
||||
cbs.add("--msl-arrayed-subpass-input", [&args](CLIParser &) { args.msl_arrayed_subpass_input = 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,17 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
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 = {};
|
||||
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;
|
||||
}
|
||||
|
@ -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(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_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,17 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(texture2d_array<float> uSubpass0 [[texture(0)]], texture2d_array<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]], uint gl_Layer [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), gl_Layer) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_Layer);
|
||||
return out;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ struct main0_out
|
||||
fragment main0_out main0(texture2d<float> uSubpass0 [[texture(0)]], texture2d<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), 0) + uSubpass1.read(uint2(gl_FragCoord.xy), 0);
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy)) + uSubpass1.read(uint2(gl_FragCoord.xy));
|
||||
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(constant uint* spvViewMask [[buffer(24)]], texture2d_array<float> uSubpass0 [[texture(0)]], texture2d_array<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]], uint gl_ViewIndex [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_ViewIndex += spvViewMask[0];
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), gl_ViewIndex) + uSubpass1.read(uint2(gl_FragCoord.xy), gl_ViewIndex);
|
||||
return out;
|
||||
}
|
||||
|
@ -13,13 +13,13 @@ struct main0_out
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d<float> uInput, thread float4& gl_FragCoord)
|
||||
{
|
||||
return uInput.read(uint2(gl_FragCoord.xy), 0);
|
||||
return uInput.read(uint2(gl_FragCoord.xy));
|
||||
}
|
||||
|
||||
fragment main0_out main0(texture2d<float> uSubpass0 [[texture(0)]], texture2d<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), 0) + load_subpasses(uSubpass1, gl_FragCoord);
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy)) + load_subpasses(uSubpass1, gl_FragCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d_ms_array<float> uInput, thread uint& gl_SampleID, thread float4& gl_FragCoord, thread uint& gl_Layer)
|
||||
{
|
||||
float4 _24 = uInput.read(uint2(gl_FragCoord.xy), gl_Layer, gl_SampleID);
|
||||
return _24;
|
||||
}
|
||||
|
||||
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 = {};
|
||||
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;
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d_ms_array<float> uInput, thread uint& gl_SampleID, thread float4& gl_FragCoord, thread uint& gl_ViewIndex)
|
||||
{
|
||||
float4 _24 = uInput.read(uint2(gl_FragCoord.xy), gl_ViewIndex, gl_SampleID);
|
||||
return _24;
|
||||
}
|
||||
|
||||
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_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,25 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d_array<float> uInput, thread float4& gl_FragCoord, thread uint& gl_Layer)
|
||||
{
|
||||
return uInput.read(uint2(gl_FragCoord.xy), gl_Layer);
|
||||
}
|
||||
|
||||
fragment main0_out main0(texture2d_array<float> uSubpass0 [[texture(0)]], texture2d_array<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]], uint gl_Layer [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), gl_Layer) + load_subpasses(uSubpass1, gl_FragCoord, gl_Layer);
|
||||
return out;
|
||||
}
|
||||
|
@ -13,13 +13,13 @@ struct main0_out
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d<float> uInput, thread float4& gl_FragCoord)
|
||||
{
|
||||
return uInput.read(uint2(gl_FragCoord.xy), 0);
|
||||
return uInput.read(uint2(gl_FragCoord.xy));
|
||||
}
|
||||
|
||||
fragment main0_out main0(texture2d<float> uSubpass0 [[texture(0)]], texture2d<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), 0) + load_subpasses(uSubpass1, gl_FragCoord);
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy)) + load_subpasses(uSubpass1, gl_FragCoord);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
26
reference/shaders-msl/frag/input-attachment.multiview.frag
Normal file
26
reference/shaders-msl/frag/input-attachment.multiview.frag
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
float4 load_subpasses(thread const texture2d_array<float> uInput, thread float4& gl_FragCoord, thread uint& gl_ViewIndex)
|
||||
{
|
||||
return uInput.read(uint2(gl_FragCoord.xy), gl_ViewIndex);
|
||||
}
|
||||
|
||||
fragment main0_out main0(constant uint* spvViewMask [[buffer(24)]], texture2d_array<float> uSubpass0 [[texture(0)]], texture2d_array<float> uSubpass1 [[texture(1)]], float4 gl_FragCoord [[position]], uint gl_ViewIndex [[render_target_array_index]])
|
||||
{
|
||||
main0_out out = {};
|
||||
gl_ViewIndex += spvViewMask[0];
|
||||
out.FragColor = uSubpass0.read(uint2(gl_FragCoord.xy), gl_ViewIndex) + load_subpasses(uSubpass1, gl_FragCoord, gl_ViewIndex);
|
||||
return out;
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
#version 450
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInputMS uSubpass1;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 load_subpasses(mediump subpassInputMS uInput)
|
||||
{
|
||||
return subpassLoad(uInput, gl_SampleID);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2) + load_subpasses(uSubpass0);
|
||||
}
|
15
shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
Normal file
15
shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
Normal file
@ -0,0 +1,15 @@
|
||||
#version 450
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInputMS uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInputMS uSubpass1;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 load_subpasses(mediump subpassInputMS uInput)
|
||||
{
|
||||
return subpassLoad(uInput, gl_SampleID);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = subpassLoad(uSubpass0, 1) + subpassLoad(uSubpass1, 2) + load_subpasses(uSubpass0);
|
||||
}
|
16
shaders-msl/frag/input-attachment.arrayed-subpass.frag
Normal file
16
shaders-msl/frag/input-attachment.arrayed-subpass.frag
Normal file
@ -0,0 +1,16 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInput uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInput uSubpass1;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 load_subpasses(mediump subpassInput uInput)
|
||||
{
|
||||
return subpassLoad(uInput);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = subpassLoad(uSubpass0) + load_subpasses(uSubpass1);
|
||||
}
|
16
shaders-msl/frag/input-attachment.multiview.frag
Normal file
16
shaders-msl/frag/input-attachment.multiview.frag
Normal file
@ -0,0 +1,16 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInput uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInput uSubpass1;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
|
||||
vec4 load_subpasses(mediump subpassInput uInput)
|
||||
{
|
||||
return subpassLoad(uInput);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = subpassLoad(uSubpass0) + load_subpasses(uSubpass1);
|
||||
}
|
@ -662,6 +662,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
|
||||
case SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING:
|
||||
options->msl.multiview_layered_rendering = value != 0;
|
||||
break;
|
||||
|
||||
case SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT:
|
||||
options->msl.arrayed_subpass_input = 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 38
|
||||
#define SPVC_C_API_VERSION_MINOR 39
|
||||
/* Bumped if internal implementation details change. */
|
||||
#define SPVC_C_API_VERSION_PATCH 0
|
||||
|
||||
@ -637,6 +637,7 @@ typedef enum spvc_compiler_option
|
||||
SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS = 66 | SPVC_COMPILER_OPTION_GLSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING = 67 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT = 68 | SPVC_COMPILER_OPTION_MSL_BIT,
|
||||
|
||||
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
|
||||
} spvc_compiler_option;
|
||||
|
167
spirv_msl.cpp
167
spirv_msl.cpp
@ -173,6 +173,7 @@ void CompilerMSL::build_implicit_builtins()
|
||||
bool has_subgroup_invocation_id = false;
|
||||
bool has_subgroup_size = false;
|
||||
bool has_view_idx = false;
|
||||
bool has_layer = false;
|
||||
uint32_t workgroup_id_type = 0;
|
||||
|
||||
// FIXME: Investigate the fact that there are no checks for the entry point interface variables.
|
||||
@ -196,12 +197,32 @@ void CompilerMSL::build_implicit_builtins()
|
||||
if (var.storage != StorageClassInput)
|
||||
return;
|
||||
|
||||
if (need_subpass_input && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) &&
|
||||
builtin == BuiltInFragCoord)
|
||||
if (need_subpass_input && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses))
|
||||
{
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var.self);
|
||||
builtin_frag_coord_id = var.self;
|
||||
has_frag_coord = true;
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInFragCoord:
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var.self);
|
||||
builtin_frag_coord_id = var.self;
|
||||
has_frag_coord = true;
|
||||
break;
|
||||
case BuiltInLayer:
|
||||
if (!msl_options.arrayed_subpass_input || msl_options.multiview)
|
||||
break;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInLayer, var.self);
|
||||
builtin_layer_id = var.self;
|
||||
has_layer = true;
|
||||
break;
|
||||
case BuiltInViewIndex:
|
||||
if (!msl_options.multiview)
|
||||
break;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var.self);
|
||||
builtin_view_idx_id = var.self;
|
||||
has_view_idx = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_sample_pos && builtin == BuiltInSampleId)
|
||||
@ -308,33 +329,79 @@ void CompilerMSL::build_implicit_builtins()
|
||||
});
|
||||
|
||||
// Use Metal's native frame-buffer fetch API for subpass inputs.
|
||||
if (!has_frag_coord && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) &&
|
||||
need_subpass_input)
|
||||
if ((!has_frag_coord || (msl_options.multiview && !has_view_idx) ||
|
||||
(msl_options.arrayed_subpass_input && !msl_options.multiview && !has_layer)) &&
|
||||
(!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) && need_subpass_input)
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(3);
|
||||
uint32_t type_id = offset;
|
||||
uint32_t type_ptr_id = offset + 1;
|
||||
uint32_t var_id = offset + 2;
|
||||
if (!has_frag_coord)
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(3);
|
||||
uint32_t type_id = offset;
|
||||
uint32_t type_ptr_id = offset + 1;
|
||||
uint32_t var_id = offset + 2;
|
||||
|
||||
// Create gl_FragCoord.
|
||||
SPIRType vec4_type;
|
||||
vec4_type.basetype = SPIRType::Float;
|
||||
vec4_type.width = 32;
|
||||
vec4_type.vecsize = 4;
|
||||
set<SPIRType>(type_id, vec4_type);
|
||||
// Create gl_FragCoord.
|
||||
SPIRType vec4_type;
|
||||
vec4_type.basetype = SPIRType::Float;
|
||||
vec4_type.width = 32;
|
||||
vec4_type.vecsize = 4;
|
||||
set<SPIRType>(type_id, vec4_type);
|
||||
|
||||
SPIRType vec4_type_ptr;
|
||||
vec4_type_ptr = vec4_type;
|
||||
vec4_type_ptr.pointer = true;
|
||||
vec4_type_ptr.parent_type = type_id;
|
||||
vec4_type_ptr.storage = StorageClassInput;
|
||||
auto &ptr_type = set<SPIRType>(type_ptr_id, vec4_type_ptr);
|
||||
ptr_type.self = type_id;
|
||||
SPIRType vec4_type_ptr;
|
||||
vec4_type_ptr = vec4_type;
|
||||
vec4_type_ptr.pointer = true;
|
||||
vec4_type_ptr.parent_type = type_id;
|
||||
vec4_type_ptr.storage = StorageClassInput;
|
||||
auto &ptr_type = set<SPIRType>(type_ptr_id, vec4_type_ptr);
|
||||
ptr_type.self = type_id;
|
||||
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInFragCoord);
|
||||
builtin_frag_coord_id = var_id;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var_id);
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInFragCoord);
|
||||
builtin_frag_coord_id = var_id;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var_id);
|
||||
}
|
||||
|
||||
if (!has_layer && msl_options.arrayed_subpass_input && !msl_options.multiview)
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(2);
|
||||
uint32_t type_ptr_id = offset;
|
||||
uint32_t var_id = offset + 1;
|
||||
|
||||
// Create gl_Layer.
|
||||
SPIRType uint_type_ptr;
|
||||
uint_type_ptr = get_uint_type();
|
||||
uint_type_ptr.pointer = true;
|
||||
uint_type_ptr.parent_type = get_uint_type_id();
|
||||
uint_type_ptr.storage = StorageClassInput;
|
||||
auto &ptr_type = set<SPIRType>(type_ptr_id, uint_type_ptr);
|
||||
ptr_type.self = get_uint_type_id();
|
||||
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInLayer);
|
||||
builtin_layer_id = var_id;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInLayer, var_id);
|
||||
}
|
||||
|
||||
if (!has_view_idx && msl_options.multiview)
|
||||
{
|
||||
uint32_t offset = ir.increase_bound_by(2);
|
||||
uint32_t type_ptr_id = offset;
|
||||
uint32_t var_id = offset + 1;
|
||||
|
||||
// Create gl_ViewIndex.
|
||||
SPIRType uint_type_ptr;
|
||||
uint_type_ptr = get_uint_type();
|
||||
uint_type_ptr.pointer = true;
|
||||
uint_type_ptr.parent_type = get_uint_type_id();
|
||||
uint_type_ptr.storage = StorageClassInput;
|
||||
auto &ptr_type = set<SPIRType>(type_ptr_id, uint_type_ptr);
|
||||
ptr_type.self = get_uint_type_id();
|
||||
|
||||
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
|
||||
set_decoration(var_id, DecorationBuiltIn, BuiltInViewIndex);
|
||||
builtin_view_idx_id = var_id;
|
||||
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_sample_id && need_sample_pos)
|
||||
@ -1310,6 +1377,18 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
||||
// Implicitly reads gl_FragCoord.
|
||||
assert(builtin_frag_coord_id != 0);
|
||||
added_arg_ids.insert(builtin_frag_coord_id);
|
||||
if (msl_options.multiview)
|
||||
{
|
||||
// Implicitly reads gl_ViewIndex.
|
||||
assert(builtin_view_idx_id != 0);
|
||||
added_arg_ids.insert(builtin_view_idx_id);
|
||||
}
|
||||
else if (msl_options.arrayed_subpass_input)
|
||||
{
|
||||
// Implicitly reads gl_Layer.
|
||||
assert(builtin_layer_id != 0);
|
||||
added_arg_ids.insert(builtin_layer_id);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -8107,10 +8186,8 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
|
||||
case DimSubpassData:
|
||||
// If we're using Metal's native frame-buffer fetch API for subpass inputs,
|
||||
// this path will not be hit.
|
||||
if (imgtype.image.ms)
|
||||
tex_coords = "uint2(gl_FragCoord.xy)";
|
||||
else
|
||||
tex_coords = join("uint2(gl_FragCoord.xy), 0");
|
||||
tex_coords = "uint2(gl_FragCoord.xy)";
|
||||
alt_coord_component = 2;
|
||||
break;
|
||||
|
||||
case Dim2D:
|
||||
@ -8227,12 +8304,30 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
|
||||
{
|
||||
// Special case for cube arrays, face and layer are packed in one dimension.
|
||||
if (imgtype.image.dim == DimCube && args.base.is_fetch)
|
||||
{
|
||||
farg_str += ", uint(" + to_extract_component_expression(args.coord, 2) + ") / 6u";
|
||||
}
|
||||
else
|
||||
{
|
||||
farg_str +=
|
||||
", uint(" +
|
||||
round_fp_tex_coords(to_extract_component_expression(args.coord, alt_coord_component), coord_is_fp) +
|
||||
")";
|
||||
if (imgtype.image.dim == DimSubpassData)
|
||||
{
|
||||
if (msl_options.multiview)
|
||||
farg_str += " + gl_ViewIndex";
|
||||
else if (msl_options.arrayed_subpass_input)
|
||||
farg_str += " + gl_Layer";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (imgtype.image.dim == DimSubpassData)
|
||||
{
|
||||
if (msl_options.multiview)
|
||||
farg_str += ", gl_ViewIndex";
|
||||
else if (msl_options.arrayed_subpass_input)
|
||||
farg_str += ", gl_Layer";
|
||||
}
|
||||
}
|
||||
|
||||
@ -11576,6 +11671,9 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
||||
case Dim1D:
|
||||
case Dim2D:
|
||||
case DimSubpassData:
|
||||
{
|
||||
bool subpass_array =
|
||||
img_type.dim == DimSubpassData && (msl_options.multiview || msl_options.arrayed_subpass_input);
|
||||
if (img_type.dim == Dim1D && !msl_options.texture_1D_as_2D)
|
||||
{
|
||||
// Use a native Metal 1D texture
|
||||
@ -11590,7 +11688,7 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
||||
img_type_4.vecsize = 4;
|
||||
return type_to_glsl(img_type_4);
|
||||
}
|
||||
if (img_type.ms && img_type.arrayed)
|
||||
if (img_type.ms && (img_type.arrayed || subpass_array))
|
||||
{
|
||||
if (!msl_options.supports_msl_version(2, 1))
|
||||
SPIRV_CROSS_THROW("Multisampled array textures are supported from 2.1.");
|
||||
@ -11598,11 +11696,12 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
|
||||
}
|
||||
else if (img_type.ms)
|
||||
img_type_name += "texture2d_ms";
|
||||
else if (img_type.arrayed)
|
||||
else if (img_type.arrayed || subpass_array)
|
||||
img_type_name += "texture2d_array";
|
||||
else
|
||||
img_type_name += "texture2d";
|
||||
break;
|
||||
}
|
||||
case Dim3D:
|
||||
img_type_name += "texture3d";
|
||||
break;
|
||||
|
@ -348,6 +348,12 @@ public:
|
||||
// to index the output buffer.
|
||||
bool vertex_for_tessellation = false;
|
||||
|
||||
// Assume that SubpassData images have multiple layers. Layered input attachments
|
||||
// are addressed relative to the Layer output from the vertex pipeline. This option
|
||||
// has no effect with multiview, since all input attachments are assumed to be layered
|
||||
// and will be addressed using the current ViewIndex.
|
||||
bool arrayed_subpass_input = false;
|
||||
|
||||
enum class IndexType
|
||||
{
|
||||
None = 0,
|
||||
|
@ -298,6 +298,8 @@ def cross_compile_msl(shader, spirv, opt, iterations, paths):
|
||||
if '.fixed-sample-mask.' in shader:
|
||||
msl_args.append('--msl-additional-fixed-sample-mask')
|
||||
msl_args.append('0x00000022')
|
||||
if '.arrayed-subpass.' in shader:
|
||||
msl_args.append('--msl-arrayed-subpass-input')
|
||||
|
||||
subprocess.check_call(msl_args)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user