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 ]:\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-add-shader-input ]:\n\t\tSpecify the format of the shader input at .\n" + "\t\t 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. is the vector length of the variable, which must be greater than or equal to that declared in the shader. 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-add-shader-output ]:\n\t\tSpecify the format of the shader output at .\n" + "\t\t 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. is the vector length of the variable, which must be greater than or equal to that declared in the shader. 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 ]:\n\t\tSpecify the format of the shader input at .\n" "\t\t 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. is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n" - "\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n" + "or other-typed variable. 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 ]:\n\t\tSpecify the format of the shader output at .\n" "\t\t 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. is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n" - "\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n" + "or other-typed variable. 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 +#include + +using namespace metal; + +template +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 z; +}; + +struct TheBlock +{ + spvUnsafeArray blockFa; + spvUnsafeArray blockSa; + float blockF; +}; + +struct main0_patchOut +{ + float2 in_te_positionScale; + float2 in_te_positionOffset; + spvUnsafeArray 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 +#include + +using namespace metal; + +template +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 z; +}; + +struct TheBlock +{ + spvUnsafeArray blockFa; + spvUnsafeArray blockSa; + float blockF; +}; + +struct main0_patchOut +{ + float2 in_te_positionScale; + float2 in_te_positionOffset; + spvUnsafeArray 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(compiler->compiler.get()); + MSLShaderInterfaceVariable input; + input.location = si->location; + input.format = static_cast(si->format); + input.builtin = static_cast(si->builtin); + input.vecsize = si->vecsize; + input.rate = static_cast(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(compiler->compiler.get()); + MSLShaderInterfaceVariable output; + output.location = so->location; + output.format = static_cast(so->format); + output.builtin = static_cast(so->builtin); + output.vecsize = so->vecsize; + output.rate = static_cast(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(var_default.format); + var->builtin = static_cast(var_default.builtin); + var->vecsize = var_default.vecsize; + var->rate = static_cast(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,13 +347,39 @@ 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 { @@ -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(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.