diff --git a/reference/opt/shaders-msl/tese/set-from-function.tese b/reference/opt/shaders-msl/tese/set-from-function.tese new file mode 100644 index 00000000..6dcdbe19 --- /dev/null +++ b/reference/opt/shaders-msl/tese/set-from-function.tese @@ -0,0 +1,55 @@ +#include +#include + +using namespace metal; + +struct Block +{ + float4 a; + float4 b; +}; + +struct Foo +{ + float4 a; + float4 b; +}; + +struct main0_out +{ + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 vColor [[attribute(0)]]; + float4 Block_a [[attribute(2)]]; + float4 Block_b [[attribute(3)]]; +}; + +struct main0_patchIn +{ + float4 vColors [[attribute(1)]]; + float4 Foo_a [[attribute(4)]]; + float4 Foo_b [[attribute(5)]]; + patch_control_point gl_in; +}; + +[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]]) +{ + main0_out out = {}; + Foo vFoo = {}; + vFoo.a = patchIn.Foo_a; + vFoo.b = patchIn.Foo_b; + out.gl_Position = patchIn.gl_in[0].Block_a; + out.gl_Position += patchIn.gl_in[0].Block_b; + out.gl_Position += patchIn.gl_in[1].Block_a; + out.gl_Position += patchIn.gl_in[1].Block_b; + out.gl_Position += patchIn.gl_in[0].vColor; + out.gl_Position += patchIn.gl_in[1].vColor; + out.gl_Position += patchIn.vColors; + out.gl_Position += vFoo.a; + out.gl_Position += vFoo.b; + return out; +} + diff --git a/reference/shaders-msl/tese/set-from-function.tese b/reference/shaders-msl/tese/set-from-function.tese new file mode 100644 index 00000000..f6e41ee5 --- /dev/null +++ b/reference/shaders-msl/tese/set-from-function.tese @@ -0,0 +1,62 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct Block +{ + float4 a; + float4 b; +}; + +struct Foo +{ + float4 a; + float4 b; +}; + +struct main0_out +{ + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float4 vColor [[attribute(0)]]; + float4 Block_a [[attribute(2)]]; + float4 Block_b [[attribute(3)]]; +}; + +struct main0_patchIn +{ + float4 vColors [[attribute(1)]]; + float4 Foo_a [[attribute(4)]]; + float4 Foo_b [[attribute(5)]]; + patch_control_point gl_in; +}; + +void set_from_function(thread float4& gl_Position, thread patch_control_point& gl_in, thread float4& vColors, thread Foo& vFoo) +{ + gl_Position = gl_in[0].Block_a; + gl_Position += gl_in[0].Block_b; + gl_Position += gl_in[1].Block_a; + gl_Position += gl_in[1].Block_b; + gl_Position += gl_in[0].vColor; + gl_Position += gl_in[1].vColor; + gl_Position += vColors; + gl_Position += vFoo.a; + gl_Position += vFoo.b; +} + +[[ patch(quad, 0) ]] vertex main0_out main0(main0_patchIn patchIn [[stage_in]]) +{ + main0_out out = {}; + Foo vFoo = {}; + vFoo.a = patchIn.Foo_a; + vFoo.b = patchIn.Foo_b; + set_from_function(out.gl_Position, patchIn.gl_in, patchIn.vColors, vFoo); + return out; +} + diff --git a/shaders-msl/tese/set-from-function.tese b/shaders-msl/tese/set-from-function.tese new file mode 100644 index 00000000..6cbab9e5 --- /dev/null +++ b/shaders-msl/tese/set-from-function.tese @@ -0,0 +1,36 @@ +#version 450 + +layout(ccw, quads, fractional_even_spacing) in; + +layout(location = 0) in vec4 vColor[]; +layout(location = 1) patch in vec4 vColors; +layout(location = 2) in Block +{ + vec4 a; + vec4 b; +} blocks[]; + +struct Foo +{ + vec4 a; + vec4 b; +}; +layout(location = 4) patch in Foo vFoo; + +void set_from_function() +{ + gl_Position = blocks[0].a; + gl_Position += blocks[0].b; + gl_Position += blocks[1].a; + gl_Position += blocks[1].b; + gl_Position += vColor[0]; + gl_Position += vColor[1]; + gl_Position += vColors; + gl_Position += vFoo.a; + gl_Position += vFoo.b; +} + +void main() +{ + set_from_function(); +} diff --git a/spirv_msl.cpp b/spirv_msl.cpp index af13d40a..0bcc8ee2 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -878,7 +878,7 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std:: if (((is_tessellation_shader() && var.storage == StorageClassInput) || (get_execution_model() == ExecutionModelTessellationControl && var.storage == StorageClassOutput)) && - !has_decoration(arg_id, DecorationPatch) && + !(has_decoration(arg_id, DecorationPatch) || is_patch_block(*p_type)) && (!is_builtin_variable(var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance || p_type->basetype == SPIRType::Struct)) @@ -1687,7 +1687,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch) BuiltIn bi_type = BuiltIn(get_decoration(var_id, DecorationBuiltIn)); if (var.storage == storage && interface_variable_exists_in_entry_point(var.self) && !is_hidden_variable(var, incl_builtins) && type.pointer && - has_decoration(var_id, DecorationPatch) == patch && + (has_decoration(var_id, DecorationPatch) || is_patch_block(type)) == patch && (!is_builtin_variable(var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance || bi_type == BuiltInLayer || bi_type == BuiltInViewportIndex || bi_type == BuiltInFragDepth || bi_type == BuiltInSampleMask || @@ -2925,7 +2925,7 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l if (var && (var->storage == StorageClassInput || (get_execution_model() == ExecutionModelTessellationControl && var->storage == StorageClassOutput)) && - !has_decoration(ops[2], DecorationPatch) && + !(has_decoration(ops[2], DecorationPatch) || is_patch_block(get_variable_data_type(*var))) && (!is_builtin_variable(*var) || bi_type == BuiltInPosition || bi_type == BuiltInPointSize || bi_type == BuiltInClipDistance || bi_type == BuiltInCullDistance || get_variable_data_type(*var).basetype == SPIRType::Struct)) @@ -4652,6 +4652,21 @@ string CompilerMSL::to_swizzle_expression(uint32_t id) } } +// Checks whether the type is a Block all of whose members have DecorationPatch. +bool CompilerMSL::is_patch_block(const SPIRType &type) +{ + if (!has_decoration(type.self, DecorationBlock)) + return false; + + for (uint32_t i = 0; i < type.member_types.size(); i++) + { + if (!has_member_decoration(type.self, i, DecorationPatch)) + return false; + } + + return true; +} + // Checks whether the ID is a row_major matrix that requires conversion before use bool CompilerMSL::is_non_native_row_major_matrix(uint32_t id) { diff --git a/spirv_msl.hpp b/spirv_msl.hpp index bb7b9d21..742975b3 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -388,6 +388,7 @@ protected: void replace_illegal_names() override; void declare_undefined_values() override; void declare_constant_arrays(); + bool is_patch_block(const SPIRType &type); bool is_non_native_row_major_matrix(uint32_t id) override; bool member_is_non_native_row_major_matrix(const SPIRType &type, uint32_t index) override; std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type, bool is_packed) override;