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:
-rw-r--r--main.cpp68
-rw-r--r--reference/opt/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc123
-rw-r--r--reference/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc111
-rw-r--r--shaders-msl/tesc/arrayed-block-io.multi-patch.tesc64
-rw-r--r--spirv_cross_c.cpp64
-rw-r--r--spirv_cross_c.h36
-rw-r--r--spirv_msl.cpp20
-rw-r--r--spirv_msl.hpp12
8 files changed, 483 insertions, 15 deletions
diff --git a/main.cpp b/main.cpp
index 0c84ac2a..aa6fa512 100644
--- a/main.cpp
+++ b/main.cpp
@@ -879,14 +879,24 @@ static void print_help_msl()
"\t[--msl-disable-frag-stencil-ref-builtin]:\n\t\tDisable FragStencilRef output. Useful if pipeline does not enable stencil output, as pipeline creation might otherwise fail.\n"
"\t[--msl-enable-frag-output-mask <mask>]:\n\t\tOnly selectively enable fragment outputs. Useful if pipeline does not enable fragment output for certain locations, as pipeline creation might otherwise fail.\n"
"\t[--msl-no-clip-distance-user-varying]:\n\t\tDo not emit user varyings to emulate gl_ClipDistance in fragment shaders.\n"
- "\t[--msl-shader-input <index> <format> <size>]:\n\t\tSpecify the format of the shader input at <index>.\n"
+ "\t[--msl-add-shader-input <index> <format> <size> <rate>]:\n\t\tSpecify the format of the shader input at <index>.\n"
"\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
- "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n"
+ "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader. <rate> can be 'vertex', "
+ "'primitive', or 'patch' to indicate a per-vertex, per-primitive, or per-patch variable.\n"
"\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n"
- "\t[--msl-shader-output <index> <format> <size>]:\n\t\tSpecify the format of the shader output at <index>.\n"
+ "\t[--msl-add-shader-output <index> <format> <size> <rate>]:\n\t\tSpecify the format of the shader output at <index>.\n"
"\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
- "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n"
+ "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader. <rate> can be 'vertex', "
+ "'primitive', or 'patch' to indicate a per-vertex, per-primitive, or per-patch variable.\n"
"\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n"
+ "\t[--msl-shader-input <index> <format> <size>]:\n\t\tSpecify the format of the shader input at <index>.\n"
+ "\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
+ "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader."
+ "\t\tEquivalent to --msl-add-shader-input with a rate of 'vertex'.\n"
+ "\t[--msl-shader-output <index> <format> <size>]:\n\t\tSpecify the format of the shader output at <index>.\n"
+ "\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
+ "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader."
+ "\t\tEquivalent to --msl-add-shader-output with a rate of 'vertex'.\n"
"\t[--msl-raw-buffer-tese-input]:\n\t\tUse raw buffers for tessellation evaluation input.\n"
"\t\tThis allows the use of nested structures and arrays.\n"
"\t\tIn a future version of SPIRV-Cross, this will become the default.\n"
@@ -1614,6 +1624,56 @@ static int main_inner(int argc, char *argv[])
[&args](CLIParser &parser) { args.msl_enable_frag_output_mask = parser.next_hex_uint(); });
cbs.add("--msl-no-clip-distance-user-varying",
[&args](CLIParser &) { args.msl_enable_clip_distance_user_varying = false; });
+ cbs.add("--msl-add-shader-input", [&args](CLIParser &parser) {
+ MSLShaderInterfaceVariable input;
+ // Make sure next_uint() is called in-order.
+ input.location = parser.next_uint();
+ const char *format = parser.next_value_string("other");
+ if (strcmp(format, "any32") == 0)
+ input.format = MSL_SHADER_VARIABLE_FORMAT_ANY32;
+ else if (strcmp(format, "any16") == 0)
+ input.format = MSL_SHADER_VARIABLE_FORMAT_ANY16;
+ else if (strcmp(format, "u16") == 0)
+ input.format = MSL_SHADER_VARIABLE_FORMAT_UINT16;
+ else if (strcmp(format, "u8") == 0)
+ input.format = MSL_SHADER_VARIABLE_FORMAT_UINT8;
+ else
+ input.format = MSL_SHADER_VARIABLE_FORMAT_OTHER;
+ input.vecsize = parser.next_uint();
+ const char *rate = parser.next_value_string("vertex");
+ if (strcmp(rate, "primitive") == 0)
+ input.rate = MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE;
+ else if (strcmp(rate, "patch") == 0)
+ input.rate = MSL_SHADER_VARIABLE_RATE_PER_PATCH;
+ else
+ input.rate = MSL_SHADER_VARIABLE_RATE_PER_VERTEX;
+ args.msl_shader_inputs.push_back(input);
+ });
+ cbs.add("--msl-add-shader-output", [&args](CLIParser &parser) {
+ MSLShaderInterfaceVariable output;
+ // Make sure next_uint() is called in-order.
+ output.location = parser.next_uint();
+ const char *format = parser.next_value_string("other");
+ if (strcmp(format, "any32") == 0)
+ output.format = MSL_SHADER_VARIABLE_FORMAT_ANY32;
+ else if (strcmp(format, "any16") == 0)
+ output.format = MSL_SHADER_VARIABLE_FORMAT_ANY16;
+ else if (strcmp(format, "u16") == 0)
+ output.format = MSL_SHADER_VARIABLE_FORMAT_UINT16;
+ else if (strcmp(format, "u8") == 0)
+ output.format = MSL_SHADER_VARIABLE_FORMAT_UINT8;
+ else
+ output.format = MSL_SHADER_VARIABLE_FORMAT_OTHER;
+ output.vecsize = parser.next_uint();
+ const char *rate = parser.next_value_string("vertex");
+ if (strcmp(rate, "primitive") == 0)
+ output.rate = MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE;
+ else if (strcmp(rate, "patch") == 0)
+ output.rate = MSL_SHADER_VARIABLE_RATE_PER_PATCH;
+ else
+ output.rate = MSL_SHADER_VARIABLE_RATE_PER_VERTEX;
+ args.msl_shader_outputs.push_back(output);
+ });
cbs.add("--msl-shader-input", [&args](CLIParser &parser) {
MSLShaderInterfaceVariable input;
// Make sure next_uint() is called in-order.
diff --git a/reference/opt/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc b/reference/opt/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
new file mode 100644
index 00000000..1618eaa6
--- /dev/null
+++ b/reference/opt/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
@@ -0,0 +1,123 @@
+#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 S
+{
+ int x;
+ float4 y;
+ spvUnsafeArray<float, 2> z;
+};
+
+struct TheBlock
+{
+ spvUnsafeArray<float, 3> blockFa;
+ spvUnsafeArray<S, 2> blockSa;
+ float blockF;
+};
+
+struct main0_patchOut
+{
+ float2 in_te_positionScale;
+ float2 in_te_positionOffset;
+ spvUnsafeArray<TheBlock, 2> tcBlock;
+};
+
+struct main0_in
+{
+ float3 in_tc_attr;
+ ushort2 m_196;
+};
+
+kernel void main0(uint3 gl_GlobalInvocationID [[thread_position_in_grid]], constant uint* spvIndirectParams [[buffer(29)]], device main0_patchOut* spvPatchOut [[buffer(27)]], device MTLQuadTessellationFactorsHalf* spvTessLevel [[buffer(26)]], device main0_in* spvIn [[buffer(22)]])
+{
+ device main0_patchOut& patchOut = spvPatchOut[gl_GlobalInvocationID.x / 5];
+ device main0_in* gl_in = &spvIn[min(gl_GlobalInvocationID.x / 5, spvIndirectParams[1] - 1) * spvIndirectParams[0]];
+ uint gl_PrimitiveID = min(gl_GlobalInvocationID.x / 5, spvIndirectParams[1] - 1);
+ int _163;
+ _163 = 0;
+ float _111;
+ for (float _170 = 1.2999999523162841796875; _163 < 2; _170 = _111, _163++)
+ {
+ float _169;
+ _169 = _170;
+ for (int _164 = 0; _164 < 3; )
+ {
+ patchOut.tcBlock[_163].blockFa[_164] = _169;
+ _169 += 0.4000000059604644775390625;
+ _164++;
+ continue;
+ }
+ int _165;
+ float _168;
+ _168 = _169;
+ _165 = 0;
+ float _174;
+ for (; _165 < 2; _168 = _174, _165++)
+ {
+ patchOut.tcBlock[_163].blockSa[_165].x = int(_168);
+ patchOut.tcBlock[_163].blockSa[_165].y = float4(_168 + 0.4000000059604644775390625, _168 + 1.2000000476837158203125, _168 + 2.0, _168 + 2.80000019073486328125);
+ _174 = _168 + 0.800000011920928955078125;
+ for (int _171 = 0; _171 < 2; )
+ {
+ patchOut.tcBlock[_163].blockSa[_165].z[_171] = _174;
+ _174 += 0.4000000059604644775390625;
+ _171++;
+ continue;
+ }
+ }
+ patchOut.tcBlock[_163].blockF = _168;
+ _111 = _168 + 0.4000000059604644775390625;
+ }
+ spvTessLevel[gl_PrimitiveID].insideTessellationFactor[0] = half(gl_in[0].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].insideTessellationFactor[1] = half(gl_in[1].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(gl_in[2].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(gl_in[3].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(gl_in[4].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[3] = half(gl_in[5].in_tc_attr.x);
+ patchOut.in_te_positionScale = float2(gl_in[6].in_tc_attr.x, gl_in[7].in_tc_attr.x);
+ patchOut.in_te_positionOffset = float2(gl_in[8].in_tc_attr.x, gl_in[9].in_tc_attr.x);
+}
+
diff --git a/reference/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc b/reference/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
new file mode 100644
index 00000000..c11c7410
--- /dev/null
+++ b/reference/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
@@ -0,0 +1,111 @@
+#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 S
+{
+ int x;
+ float4 y;
+ spvUnsafeArray<float, 2> z;
+};
+
+struct TheBlock
+{
+ spvUnsafeArray<float, 3> blockFa;
+ spvUnsafeArray<S, 2> blockSa;
+ float blockF;
+};
+
+struct main0_patchOut
+{
+ float2 in_te_positionScale;
+ float2 in_te_positionOffset;
+ spvUnsafeArray<TheBlock, 2> tcBlock;
+};
+
+struct main0_in
+{
+ float3 in_tc_attr;
+ ushort2 m_179;
+};
+
+kernel void main0(uint3 gl_GlobalInvocationID [[thread_position_in_grid]], constant uint* spvIndirectParams [[buffer(29)]], device main0_patchOut* spvPatchOut [[buffer(27)]], device MTLQuadTessellationFactorsHalf* spvTessLevel [[buffer(26)]], device main0_in* spvIn [[buffer(22)]])
+{
+ device main0_patchOut& patchOut = spvPatchOut[gl_GlobalInvocationID.x / 5];
+ device main0_in* gl_in = &spvIn[min(gl_GlobalInvocationID.x / 5, spvIndirectParams[1] - 1) * spvIndirectParams[0]];
+ uint gl_PrimitiveID = min(gl_GlobalInvocationID.x / 5, spvIndirectParams[1] - 1);
+ float v = 1.2999999523162841796875;
+ for (int i0 = 0; i0 < 2; i0++)
+ {
+ for (int i1 = 0; i1 < 3; i1++)
+ {
+ patchOut.tcBlock[i0].blockFa[i1] = v;
+ v += 0.4000000059604644775390625;
+ }
+ for (int i1_1 = 0; i1_1 < 2; i1_1++)
+ {
+ patchOut.tcBlock[i0].blockSa[i1_1].x = int(v);
+ v += 0.4000000059604644775390625;
+ patchOut.tcBlock[i0].blockSa[i1_1].y = float4(v, v + 0.800000011920928955078125, v + 1.60000002384185791015625, v + 2.400000095367431640625);
+ v += 0.4000000059604644775390625;
+ for (int i2 = 0; i2 < 2; i2++)
+ {
+ patchOut.tcBlock[i0].blockSa[i1_1].z[i2] = v;
+ v += 0.4000000059604644775390625;
+ }
+ }
+ patchOut.tcBlock[i0].blockF = v;
+ v += 0.4000000059604644775390625;
+ }
+ spvTessLevel[gl_PrimitiveID].insideTessellationFactor[0] = half(gl_in[0].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].insideTessellationFactor[1] = half(gl_in[1].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[0] = half(gl_in[2].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[1] = half(gl_in[3].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[2] = half(gl_in[4].in_tc_attr.x);
+ spvTessLevel[gl_PrimitiveID].edgeTessellationFactor[3] = half(gl_in[5].in_tc_attr.x);
+ patchOut.in_te_positionScale = float2(gl_in[6].in_tc_attr.x, gl_in[7].in_tc_attr.x);
+ patchOut.in_te_positionOffset = float2(gl_in[8].in_tc_attr.x, gl_in[9].in_tc_attr.x);
+}
+
diff --git a/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc b/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
new file mode 100644
index 00000000..0fc300d6
--- /dev/null
+++ b/shaders-msl/tesc/arrayed-block-io.multi-patch.tesc
@@ -0,0 +1,64 @@
+#version 310 es
+#extension GL_EXT_tessellation_shader : require
+
+layout(vertices = 5) out;
+
+layout(location = 0) patch out highp vec2 in_te_positionScale;
+layout(location = 1) patch out highp vec2 in_te_positionOffset;
+
+struct S
+{
+ highp int x;
+ highp vec4 y;
+ highp float z[2];
+};
+layout(location = 2) patch out TheBlock
+{
+ highp float blockFa[3];
+ S blockSa[2];
+ highp float blockF;
+} tcBlock[2];
+
+layout(location = 0) in highp float in_tc_attr[];
+
+void main (void)
+{
+ {
+ highp float v = 1.3;
+
+ // Assign values to output tcBlock
+ for (int i0 = 0; i0 < 2; ++i0)
+ {
+ for (int i1 = 0; i1 < 3; ++i1)
+ {
+ tcBlock[i0].blockFa[i1] = v;
+ v += 0.4;
+ }
+ for (int i1 = 0; i1 < 2; ++i1)
+ {
+ tcBlock[i0].blockSa[i1].x = int(v);
+ v += 0.4;
+ tcBlock[i0].blockSa[i1].y = vec4(v, v+0.8, v+1.6, v+2.4);
+ v += 0.4;
+ for (int i2 = 0; i2 < 2; ++i2)
+ {
+ tcBlock[i0].blockSa[i1].z[i2] = v;
+ v += 0.4;
+ }
+ }
+ tcBlock[i0].blockF = v;
+ v += 0.4;
+ }
+ }
+
+ gl_TessLevelInner[0] = in_tc_attr[0];
+ gl_TessLevelInner[1] = in_tc_attr[1];
+
+ gl_TessLevelOuter[0] = in_tc_attr[2];
+ gl_TessLevelOuter[1] = in_tc_attr[3];
+ gl_TessLevelOuter[2] = in_tc_attr[4];
+ gl_TessLevelOuter[3] = in_tc_attr[5];
+
+ in_te_positionScale = vec2(in_tc_attr[6], in_tc_attr[7]);
+ in_te_positionOffset = vec2(in_tc_attr[8], in_tc_attr[9]);
+}
diff --git a/spirv_cross_c.cpp b/spirv_cross_c.cpp
index d227f342..4e4a0189 100644
--- a/spirv_cross_c.cpp
+++ b/spirv_cross_c.cpp
@@ -1182,6 +1182,31 @@ spvc_result spvc_compiler_msl_add_shader_input(spvc_compiler compiler, const spv
#endif
}
+spvc_result spvc_compiler_msl_add_shader_input_2(spvc_compiler compiler, const spvc_msl_shader_interface_var_2 *si)
+{
+#if SPIRV_CROSS_C_API_MSL
+ if (compiler->backend != SPVC_BACKEND_MSL)
+ {
+ compiler->context->report_error("MSL function used on a non-MSL backend.");
+ return SPVC_ERROR_INVALID_ARGUMENT;
+ }
+
+ auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
+ MSLShaderInterfaceVariable input;
+ input.location = si->location;
+ input.format = static_cast<MSLShaderVariableFormat>(si->format);
+ input.builtin = static_cast<spv::BuiltIn>(si->builtin);
+ input.vecsize = si->vecsize;
+ input.rate = static_cast<MSLShaderVariableRate>(si->rate);
+ msl.add_msl_shader_input(input);
+ return SPVC_SUCCESS;
+#else
+ (void)si;
+ compiler->context->report_error("MSL function used on a non-MSL backend.");
+ return SPVC_ERROR_INVALID_ARGUMENT;
+#endif
+}
+
spvc_result spvc_compiler_msl_add_shader_output(spvc_compiler compiler, const spvc_msl_shader_interface_var *so)
{
#if SPIRV_CROSS_C_API_MSL
@@ -1206,6 +1231,31 @@ spvc_result spvc_compiler_msl_add_shader_output(spvc_compiler compiler, const sp
#endif
}
+spvc_result spvc_compiler_msl_add_shader_output_2(spvc_compiler compiler, const spvc_msl_shader_interface_var_2 *so)
+{
+#if SPIRV_CROSS_C_API_MSL
+ if (compiler->backend != SPVC_BACKEND_MSL)
+ {
+ compiler->context->report_error("MSL function used on a non-MSL backend.");
+ return SPVC_ERROR_INVALID_ARGUMENT;
+ }
+
+ auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
+ MSLShaderInterfaceVariable output;
+ output.location = so->location;
+ output.format = static_cast<MSLShaderVariableFormat>(so->format);
+ output.builtin = static_cast<spv::BuiltIn>(so->builtin);
+ output.vecsize = so->vecsize;
+ output.rate = static_cast<MSLShaderVariableRate>(so->rate);
+ msl.add_msl_shader_output(output);
+ return SPVC_SUCCESS;
+#else
+ (void)so;
+ compiler->context->report_error("MSL function used on a non-MSL backend.");
+ return SPVC_ERROR_INVALID_ARGUMENT;
+#endif
+}
+
spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,
const spvc_msl_resource_binding *binding)
{
@@ -2595,6 +2645,20 @@ void spvc_msl_shader_input_init(spvc_msl_shader_input *input)
spvc_msl_shader_interface_var_init(input);
}
+void spvc_msl_shader_interface_var_init_2(spvc_msl_shader_interface_var_2 *var)
+{
+#if SPIRV_CROSS_C_API_MSL
+ MSLShaderInterfaceVariable var_default;
+ var->location = var_default.location;
+ var->format = static_cast<spvc_msl_shader_variable_format>(var_default.format);
+ var->builtin = static_cast<SpvBuiltIn>(var_default.builtin);
+ var->vecsize = var_default.vecsize;
+ var->rate = static_cast<spvc_msl_shader_variable_rate>(var_default.rate);
+#else
+ memset(var, 0, sizeof(*var));
+#endif
+}
+
void spvc_msl_resource_binding_init(spvc_msl_resource_binding *binding)
{
#if SPIRV_CROSS_C_API_MSL
diff --git a/spirv_cross_c.h b/spirv_cross_c.h
index a8a64d4d..7cb3ba05 100644
--- a/spirv_cross_c.h
+++ b/spirv_cross_c.h
@@ -336,7 +336,7 @@ typedef struct spvc_msl_vertex_attribute
*/
SPVC_PUBLIC_API void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr);
-/* Maps to C++ API. */
+/* Maps to C++ API. Deprecated; use spvc_msl_shader_interface_var_2. */
typedef struct spvc_msl_shader_interface_var
{
unsigned location;
@@ -347,14 +347,40 @@ typedef struct spvc_msl_shader_interface_var
/*
* Initializes the shader input struct.
+ * Deprecated. Use spvc_msl_shader_interface_var_init_2().
*/
SPVC_PUBLIC_API void spvc_msl_shader_interface_var_init(spvc_msl_shader_interface_var *var);
/*
- * Deprecated. Use spvc_msl_shader_interface_var_init().
+ * Deprecated. Use spvc_msl_shader_interface_var_init_2().
*/
SPVC_PUBLIC_API void spvc_msl_shader_input_init(spvc_msl_shader_input *input);
/* Maps to C++ API. */
+typedef enum spvc_msl_shader_variable_rate
+{
+ SPVC_MSL_SHADER_VARIABLE_RATE_PER_VERTEX = 0,
+ SPVC_MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE = 1,
+ SPVC_MSL_SHADER_VARIABLE_RATE_PER_PATCH = 2,
+
+ SPVC_MSL_SHADER_VARIABLE_RATE_INT_MAX = 0x7fffffff,
+} spvc_msl_shader_variable_rate;
+
+/* Maps to C++ API. */
+typedef struct spvc_msl_shader_interface_var_2
+{
+ unsigned location;
+ spvc_msl_shader_variable_format format;
+ SpvBuiltIn builtin;
+ unsigned vecsize;
+ spvc_msl_shader_variable_rate rate;
+} spvc_msl_shader_interface_var_2;
+
+/*
+ * Initializes the shader interface variable struct.
+ */
+SPVC_PUBLIC_API void spvc_msl_shader_interface_var_init_2(spvc_msl_shader_interface_var_2 *var);
+
+/* Maps to C++ API. */
typedef struct spvc_msl_resource_binding
{
SpvExecutionModel stage;
@@ -799,10 +825,16 @@ SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler
const spvc_msl_vertex_attribute *attrs);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,
const spvc_msl_resource_binding *binding);
+/* Deprecated; use spvc_compiler_msl_add_shader_input_2(). */
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_shader_input(spvc_compiler compiler,
const spvc_msl_shader_interface_var *input);
+SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_shader_input_2(spvc_compiler compiler,
+ const spvc_msl_shader_interface_var_2 *input);
+/* Deprecated; use spvc_compiler_msl_add_shader_output_2(). */
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_shader_output(spvc_compiler compiler,
const spvc_msl_shader_interface_var *output);
+SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_shader_output_2(spvc_compiler compiler,
+ const spvc_msl_shader_interface_var_2 *output);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler, unsigned desc_set);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_compiler compiler, unsigned desc_set, spvc_bool device_address);
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index b56edf74..07d23262 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -3359,7 +3359,8 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
if (var_type.basetype == SPIRType::Struct)
{
- bool block_requires_flattening = variable_storage_requires_stage_io(storage) || is_block;
+ bool block_requires_flattening =
+ variable_storage_requires_stage_io(storage) || (is_block && var_type.array.empty());
bool needs_local_declaration = !is_builtin && block_requires_flattening && meta.allow_local_declaration;
if (needs_local_declaration)
@@ -3978,7 +3979,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
if (location_inputs_in_use.count(input.first.location) != 0)
continue;
- if (input.second.patch != patch)
+ if (patch != (input.second.rate == MSL_SHADER_VARIABLE_RATE_PER_PATCH))
continue;
// Tessellation levels have their own struct, so there's no need to add them here.
@@ -7719,20 +7720,22 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l
bool flatten_composites = false;
bool is_block = false;
-
- if (var)
- is_block = has_decoration(get_variable_data_type(*var).self, DecorationBlock);
+ bool is_arrayed = false;
if (var)
{
+ auto &type = get_variable_data_type(*var);
+ is_block = has_decoration(type.self, DecorationBlock);
+ is_arrayed = !type.array.empty();
+
flatten_composites = variable_storage_requires_stage_io(var->storage);
- patch = has_decoration(ops[2], DecorationPatch) || is_patch_block(get_variable_data_type(*var));
+ patch = has_decoration(ops[2], DecorationPatch) || is_patch_block(type);
// Should match strip_array in add_interface_block.
flat_data = var->storage == StorageClassInput || (var->storage == StorageClassOutput && is_tesc_shader());
// Patch inputs are treated as normal block IO variables, so they don't deal with this path at all.
- if (patch && (!is_block || var->storage == StorageClassInput))
+ if (patch && (!is_block || is_arrayed || var->storage == StorageClassInput))
flat_data = false;
// We might have a chained access chain, where
@@ -12053,8 +12056,7 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id, bo
if (is_tese_shader() && msl_options.raw_buffer_tese_input && var)
{
bool is_stage_in = var->basevariable == stage_in_ptr_var_id;
- bool is_patch_stage_in = has_decoration(var->self, DecorationPatch) ||
- is_patch_block(get_variable_data_type(get<SPIRVariable>(var->basevariable)));
+ bool is_patch_stage_in = has_decoration(var->self, DecorationPatch);
bool is_builtin = has_decoration(var->self, DecorationBuiltIn);
BuiltIn builtin = (BuiltIn)get_decoration(var->self, DecorationBuiltIn);
bool is_tess_level = is_builtin && (builtin == BuiltInTessLevelOuter || builtin == BuiltInTessLevelInner);
diff --git a/spirv_msl.hpp b/spirv_msl.hpp
index 9bf7672b..bd4ecc34 100644
--- a/spirv_msl.hpp
+++ b/spirv_msl.hpp
@@ -58,6 +58,17 @@ enum MSLShaderVariableFormat
MSL_SHADER_VARIABLE_FORMAT_INT_MAX = 0x7fffffff
};
+// Indicates the rate at which a variable changes value, one of: per-vertex,
+// per-primitive, or per-patch.
+enum MSLShaderVariableRate
+{
+ MSL_SHADER_VARIABLE_RATE_PER_VERTEX = 0,
+ MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE = 1,
+ MSL_SHADER_VARIABLE_RATE_PER_PATCH = 2,
+
+ MSL_SHADER_VARIABLE_RATE_INT_MAX = 0x7fffffff,
+};
+
// Defines MSL characteristics of a shader interface variable at a particular location.
// After compilation, it is possible to query whether or not this location was used.
// If vecsize is nonzero, it must be greater than or equal to the vecsize declared in the shader,
@@ -69,6 +80,7 @@ struct MSLShaderInterfaceVariable
MSLShaderVariableFormat format = MSL_SHADER_VARIABLE_FORMAT_OTHER;
spv::BuiltIn builtin = spv::BuiltInMax;
uint32_t vecsize = 0;
+ MSLShaderVariableRate rate = MSL_SHADER_VARIABLE_RATE_PER_VERTEX;
};
// Matches the binding index of a MSL resource for a binding within a descriptor set.