Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChip Davis <cdavis@codeweavers.com>2020-08-28 03:24:20 +0300
committerChip Davis <cdavis@codeweavers.com>2020-09-02 17:18:25 +0300
commit4cf840ee7b585eca51bda0baaaecf0aae168fbaa (patch)
treeb657deed1b3f00347cb5f8253b981a6b992bc0af
parentc7507e39d471241d633f8926de04c6565ad040a0 (diff)
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.
-rw-r--r--CMakeLists.txt2
-rw-r--r--main.cpp7
-rw-r--r--reference/opt/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag17
-rw-r--r--reference/opt/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag18
-rw-r--r--reference/opt/shaders-msl/frag/input-attachment.arrayed-subpass.frag17
-rw-r--r--reference/opt/shaders-msl/frag/input-attachment.frag2
-rw-r--r--reference/opt/shaders-msl/frag/input-attachment.multiview.frag18
-rw-r--r--reference/shaders-msl-no-opt/asm/frag/input-attachment-unused-frag-coord.asm.frag4
-rw-r--r--reference/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag26
-rw-r--r--reference/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag27
-rw-r--r--reference/shaders-msl/frag/input-attachment.arrayed-subpass.frag25
-rw-r--r--reference/shaders-msl/frag/input-attachment.frag4
-rw-r--r--reference/shaders-msl/frag/input-attachment.multiview.frag26
-rw-r--r--shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag15
-rw-r--r--shaders-msl/frag/input-attachment-ms.multiview.msl21.frag15
-rw-r--r--shaders-msl/frag/input-attachment.arrayed-subpass.frag16
-rw-r--r--shaders-msl/frag/input-attachment.multiview.frag16
-rw-r--r--spirv_cross_c.cpp4
-rw-r--r--spirv_cross_c.h3
-rw-r--r--spirv_msl.cpp173
-rw-r--r--spirv_msl.hpp6
-rwxr-xr-xtest_shaders.py2
22 files changed, 398 insertions, 45 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 214672d7..6fcde405 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/main.cpp b/main.cpp
index c1098184..6e6e94aa 100644
--- a/main.cpp
+++ b/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();
diff --git a/reference/opt/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag b/reference/opt/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
new file mode 100644
index 00000000..5f137b04
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
@@ -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;
+}
+
diff --git a/reference/opt/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag b/reference/opt/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
new file mode 100644
index 00000000..2e4ca8a7
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
@@ -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;
+}
+
diff --git a/reference/opt/shaders-msl/frag/input-attachment.arrayed-subpass.frag b/reference/opt/shaders-msl/frag/input-attachment.arrayed-subpass.frag
new file mode 100644
index 00000000..5d5ee431
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/input-attachment.arrayed-subpass.frag
@@ -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;
+}
+
diff --git a/reference/opt/shaders-msl/frag/input-attachment.frag b/reference/opt/shaders-msl/frag/input-attachment.frag
index 12219064..790dce3c 100644
--- a/reference/opt/shaders-msl/frag/input-attachment.frag
+++ b/reference/opt/shaders-msl/frag/input-attachment.frag
@@ -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;
}
diff --git a/reference/opt/shaders-msl/frag/input-attachment.multiview.frag b/reference/opt/shaders-msl/frag/input-attachment.multiview.frag
new file mode 100644
index 00000000..7cf06d2d
--- /dev/null
+++ b/reference/opt/shaders-msl/frag/input-attachment.multiview.frag
@@ -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;
+}
+
diff --git a/reference/shaders-msl-no-opt/asm/frag/input-attachment-unused-frag-coord.asm.frag b/reference/shaders-msl-no-opt/asm/frag/input-attachment-unused-frag-coord.asm.frag
index d43b0adc..93bbaec0 100644
--- a/reference/shaders-msl-no-opt/asm/frag/input-attachment-unused-frag-coord.asm.frag
+++ b/reference/shaders-msl-no-opt/asm/frag/input-attachment-unused-frag-coord.asm.frag
@@ -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;
}
diff --git a/reference/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag b/reference/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
new file mode 100644
index 00000000..30ad95be
--- /dev/null
+++ b/reference/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
@@ -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;
+}
+
diff --git a/reference/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag b/reference/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
new file mode 100644
index 00000000..a2e5ef7d
--- /dev/null
+++ b/reference/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
@@ -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;
+}
+
diff --git a/reference/shaders-msl/frag/input-attachment.arrayed-subpass.frag b/reference/shaders-msl/frag/input-attachment.arrayed-subpass.frag
new file mode 100644
index 00000000..76d0a3cf
--- /dev/null
+++ b/reference/shaders-msl/frag/input-attachment.arrayed-subpass.frag
@@ -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;
+}
+
diff --git a/reference/shaders-msl/frag/input-attachment.frag b/reference/shaders-msl/frag/input-attachment.frag
index d43b0adc..93bbaec0 100644
--- a/reference/shaders-msl/frag/input-attachment.frag
+++ b/reference/shaders-msl/frag/input-attachment.frag
@@ -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;
}
diff --git a/reference/shaders-msl/frag/input-attachment.multiview.frag b/reference/shaders-msl/frag/input-attachment.multiview.frag
new file mode 100644
index 00000000..931790b8
--- /dev/null
+++ b/reference/shaders-msl/frag/input-attachment.multiview.frag
@@ -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;
+}
+
diff --git a/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag b/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
new file mode 100644
index 00000000..b3d44c94
--- /dev/null
+++ b/shaders-msl/frag/input-attachment-ms.arrayed-subpass.msl21.frag
@@ -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);
+}
diff --git a/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag b/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
new file mode 100644
index 00000000..b3d44c94
--- /dev/null
+++ b/shaders-msl/frag/input-attachment-ms.multiview.msl21.frag
@@ -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);
+}
diff --git a/shaders-msl/frag/input-attachment.arrayed-subpass.frag b/shaders-msl/frag/input-attachment.arrayed-subpass.frag
new file mode 100644
index 00000000..877d0525
--- /dev/null
+++ b/shaders-msl/frag/input-attachment.arrayed-subpass.frag
@@ -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);
+}
diff --git a/shaders-msl/frag/input-attachment.multiview.frag b/shaders-msl/frag/input-attachment.multiview.frag
new file mode 100644
index 00000000..877d0525
--- /dev/null
+++ b/shaders-msl/frag/input-attachment.multiview.frag
@@ -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);
+}
diff --git a/spirv_cross_c.cpp b/spirv_cross_c.cpp
index 7cf79392..25687f2c 100644
--- a/spirv_cross_c.cpp
+++ b/spirv_cross_c.cpp
@@ -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:
diff --git a/spirv_cross_c.h b/spirv_cross_c.h
index bb199144..06d832ce 100644
--- a/spirv_cross_c.h
+++ b/spirv_cross_c.h
@@ -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;
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index bd844b8f..68ddfb5d 100644
--- a/spirv_msl.cpp
+++ b/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)
- {
- 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);
-
- 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;
+ 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)
+ {
+ 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);
+
+ 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;
diff --git a/spirv_msl.hpp b/spirv_msl.hpp
index 9098d830..15294087 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -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,
diff --git a/test_shaders.py b/test_shaders.py
index 71e9361f..4b8a52fa 100755
--- a/test_shaders.py
+++ b/test_shaders.py
@@ -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)