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))
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;
indexable = positions;
@ -68,7 +68,7 @@ float4 consume_constant_arrays2(thread const spvUnsafeArray<float4, 4> (&positio
}
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);
}

View File

@ -58,28 +58,24 @@ struct main0_in
};
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))
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;
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<float4, 2> _42;
test(_42);
spvUnsafeArray<float4, 2> _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;
}

View File

@ -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<T> template
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.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);
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)
{