From a82ecbeba993789d0d17ba06e701dffa799bee3f Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Thu, 24 Oct 2019 13:03:38 +0200 Subject: [PATCH] MSL: Enable proper value types for return and value-passing of arrays. Now that we have spvUnsafeArray there is no need to deal with these special purpose cases. --- .../vert/pass-array-by-value.vert | 4 +- reference/shaders-msl/vert/return-array.vert | 14 ++--- spirv_msl.cpp | 56 ++----------------- 3 files changed, 13 insertions(+), 61 deletions(-) diff --git a/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert b/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert index 888fc58f..fa65d280 100644 --- a/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert +++ b/reference/shaders-msl-no-opt/vert/pass-array-by-value.vert @@ -58,7 +58,7 @@ struct main0_in }; static inline __attribute__((always_inline)) -float4 consume_constant_arrays2(thread const spvUnsafeArray (&positions), thread const spvUnsafeArray (&positions2), thread int& Index1, thread int& Index2) +float4 consume_constant_arrays2(spvUnsafeArray positions, spvUnsafeArray positions2, thread int& Index1, thread int& Index2) { spvUnsafeArray indexable; indexable = positions; @@ -68,7 +68,7 @@ float4 consume_constant_arrays2(thread const spvUnsafeArray (&positio } static inline __attribute__((always_inline)) -float4 consume_constant_arrays(thread const spvUnsafeArray (&positions), thread const spvUnsafeArray (&positions2), thread int& Index1, thread int& Index2) +float4 consume_constant_arrays(spvUnsafeArray positions, spvUnsafeArray positions2, thread int& Index1, thread int& Index2) { return consume_constant_arrays2(positions, positions2, Index1, Index2); } diff --git a/reference/shaders-msl/vert/return-array.vert b/reference/shaders-msl/vert/return-array.vert index 1ee37cf3..dacb0ba3 100644 --- a/reference/shaders-msl/vert/return-array.vert +++ b/reference/shaders-msl/vert/return-array.vert @@ -58,28 +58,24 @@ struct main0_in }; static inline __attribute__((always_inline)) -void test(thread spvUnsafeArray (&SPIRV_Cross_return_value)) +spvUnsafeArray test() { - SPIRV_Cross_return_value = _20; + return _20; } static inline __attribute__((always_inline)) -void test2(thread spvUnsafeArray (&SPIRV_Cross_return_value), thread float4& vInput0, thread float4& vInput1) +spvUnsafeArray test2(thread float4& vInput0, thread float4& vInput1) { spvUnsafeArray foobar; foobar[0] = vInput0; foobar[1] = vInput1; - SPIRV_Cross_return_value = foobar; + return foobar; } vertex main0_out main0(main0_in in [[stage_in]]) { main0_out out = {}; - spvUnsafeArray _42; - test(_42); - spvUnsafeArray _44; - test2(_44, in.vInput0, in.vInput1); - out.gl_Position = _42[0] + _44[1]; + out.gl_Position = test()[0] + test2(in.vInput0, in.vInput1)[1]; return out; } diff --git a/spirv_msl.cpp b/spirv_msl.cpp index c256f67a..27b57840 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -982,7 +982,7 @@ string CompilerMSL::compile() backend.native_row_major_matrix = false; backend.unsized_array_supported = false; backend.can_declare_arrays_inline = false; - backend.can_return_array = false; + backend.can_return_array = true; // <-- Allow Metal to use the array template backend.allow_truncated_access_chain = true; backend.array_is_value_type = true; // <-- Allow Metal to use the array template to make arrays a value type backend.comparison_image_samples_scalar = true; @@ -6765,31 +6765,11 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &) auto &type = get(func.return_type); - if (type.array.empty()) - { - decl += func_type_decl(type); - } - else - { - // We cannot return arrays in MSL, so "return" through an out variable. - decl += "void"; - } - + decl += func_type_decl(type); decl += " "; decl += to_name(func.self); decl += "("; - if (!type.array.empty()) - { - // Fake arrays returns by writing to an out array instead. - decl += "thread "; - decl += type_to_glsl(type); - decl += " (&SPIRV_Cross_return_value)"; - decl += type_to_array_glsl(type); - if (!func.arguments.empty()) - decl += ", "; - } - if (processing_entry_point) { if (msl_options.argument_buffers) @@ -9586,34 +9566,10 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg) (storage == StorageClassFunction || storage == StorageClassGeneric)) { // If the argument is a pure value and not an opaque type, we will pass by value. - if (is_array(type)) - { - // We are receiving an array by value. This is problematic. - // We cannot be sure of the target address space since we are supposed to receive a copy, - // but this is not possible with MSL without some extra work. - // We will have to assume we're getting a reference in thread address space. - // If we happen to get a reference in constant address space, the caller must emit a copy and pass that. - // Thread const therefore becomes the only logical choice, since we cannot "create" a constant array from - // non-constant arrays, but we can create thread const from constant. - decl = string("thread const ") + decl; - decl += " (&"; - const char *restrict_kw = to_restrict(name_id); - if (*restrict_kw) - { - decl += " "; - decl += restrict_kw; - } - decl += to_expression(name_id); - decl += ")"; - decl += type_to_array_glsl(type); - } - else - { - if (!address_space.empty()) - decl = join(address_space, " ", decl); - decl += " "; - decl += to_expression(name_id); - } + if (!address_space.empty()) + decl = join(address_space, " ", decl); + decl += " "; + decl += to_expression(name_id); } else if (is_array(type) && !type_is_image) {