MSL: Enable proper value types for return and value-passing of arrays.

Now that we have spvUnsafeArray<T> there is no need to deal with these
special purpose cases.
This commit is contained in:
Hans-Kristian Arntzen 2019-10-24 13:03:38 +02:00
parent 4ac12594c9
commit a82ecbeba9
3 changed files with 13 additions and 61 deletions

View File

@ -58,7 +58,7 @@ struct main0_in
}; };
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
float4 consume_constant_arrays2(thread const spvUnsafeArray<float4, 4> (&positions), thread const spvUnsafeArray<float4, 4> (&positions2), thread int& Index1, thread int& Index2) float4 consume_constant_arrays2(spvUnsafeArray<float4, 4> positions, spvUnsafeArray<float4, 4> positions2, thread int& Index1, thread int& Index2)
{ {
spvUnsafeArray<float4, 4> indexable; spvUnsafeArray<float4, 4> indexable;
indexable = positions; indexable = positions;
@ -68,7 +68,7 @@ float4 consume_constant_arrays2(thread const spvUnsafeArray<float4, 4> (&positio
} }
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
float4 consume_constant_arrays(thread const spvUnsafeArray<float4, 4> (&positions), thread const spvUnsafeArray<float4, 4> (&positions2), thread int& Index1, thread int& Index2) float4 consume_constant_arrays(spvUnsafeArray<float4, 4> positions, spvUnsafeArray<float4, 4> positions2, thread int& Index1, thread int& Index2)
{ {
return consume_constant_arrays2(positions, positions2, Index1, Index2); return consume_constant_arrays2(positions, positions2, Index1, Index2);
} }

View File

@ -58,28 +58,24 @@ struct main0_in
}; };
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
void test(thread spvUnsafeArray<float4, 2> (&SPIRV_Cross_return_value)) spvUnsafeArray<float4, 2> test()
{ {
SPIRV_Cross_return_value = _20; return _20;
} }
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
void test2(thread spvUnsafeArray<float4, 2> (&SPIRV_Cross_return_value), thread float4& vInput0, thread float4& vInput1) spvUnsafeArray<float4, 2> test2(thread float4& vInput0, thread float4& vInput1)
{ {
spvUnsafeArray<float4, 2> foobar; spvUnsafeArray<float4, 2> foobar;
foobar[0] = vInput0; foobar[0] = vInput0;
foobar[1] = vInput1; foobar[1] = vInput1;
SPIRV_Cross_return_value = foobar; return foobar;
} }
vertex main0_out main0(main0_in in [[stage_in]]) vertex main0_out main0(main0_in in [[stage_in]])
{ {
main0_out out = {}; main0_out out = {};
spvUnsafeArray<float4, 2> _42; out.gl_Position = test()[0] + test2(in.vInput0, in.vInput1)[1];
test(_42);
spvUnsafeArray<float4, 2> _44;
test2(_44, in.vInput0, in.vInput1);
out.gl_Position = _42[0] + _44[1];
return out; return out;
} }

View File

@ -982,7 +982,7 @@ string CompilerMSL::compile()
backend.native_row_major_matrix = false; backend.native_row_major_matrix = false;
backend.unsized_array_supported = false; backend.unsized_array_supported = false;
backend.can_declare_arrays_inline = false; backend.can_declare_arrays_inline = false;
backend.can_return_array = false; backend.can_return_array = true; // <-- Allow Metal to use the array<T> template
backend.allow_truncated_access_chain = true; backend.allow_truncated_access_chain = true;
backend.array_is_value_type = true; // <-- Allow Metal to use the array<T> template to make arrays a value type backend.array_is_value_type = true; // <-- Allow Metal to use the array<T> template to make arrays a value type
backend.comparison_image_samples_scalar = true; backend.comparison_image_samples_scalar = true;
@ -6765,31 +6765,11 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
auto &type = get<SPIRType>(func.return_type); auto &type = get<SPIRType>(func.return_type);
if (type.array.empty())
{
decl += func_type_decl(type); decl += func_type_decl(type);
}
else
{
// We cannot return arrays in MSL, so "return" through an out variable.
decl += "void";
}
decl += " "; decl += " ";
decl += to_name(func.self); decl += to_name(func.self);
decl += "("; 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 (processing_entry_point)
{ {
if (msl_options.argument_buffers) if (msl_options.argument_buffers)
@ -9586,35 +9566,11 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
(storage == StorageClassFunction || storage == StorageClassGeneric)) (storage == StorageClassFunction || storage == StorageClassGeneric))
{ {
// If the argument is a pure value and not an opaque type, we will pass by value. // 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()) if (!address_space.empty())
decl = join(address_space, " ", decl); decl = join(address_space, " ", decl);
decl += " "; decl += " ";
decl += to_expression(name_id); decl += to_expression(name_id);
} }
}
else if (is_array(type) && !type_is_image) else if (is_array(type) && !type_is_image)
{ {
// Arrays of images and samplers are special cased. // Arrays of images and samplers are special cased.