MSL: Reinstate workaround for returning arrays.

This commit is contained in:
Hans-Kristian Arntzen 2020-02-24 13:04:10 +01:00
parent c9d4f9cd74
commit 20b28f72fa
5 changed files with 170 additions and 6 deletions

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
};
struct main0_in
{
float4 vInput1 [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(10.0) + in.vInput1;
return out;
}

View File

@ -184,7 +184,7 @@ inline void spvArrayCopyFromThreadGroupToThreadGroup3(threadgroup T (&dst)[A][B]
kernel void main0(device BUF& o [[buffer(0)]]) kernel void main0(device BUF& o [[buffer(0)]])
{ {
float c[2][2][2]; float c[2][2][2];
spvArrayCopyFromConstantToStack3(c.elements, _21); spvArrayCopyFromConstantToStack3(c, _21);
o.a = int(c[1][1][1]); o.a = int(c[1][1][1]);
float _43[2] = { o.b, o.c }; float _43[2] = { o.b, o.c };
float _48[2] = { o.b, o.b }; float _48[2] = { o.b, o.b };
@ -194,9 +194,9 @@ kernel void main0(device BUF& o [[buffer(0)]])
float _60[2][2] = { { _54[0], _54[1] }, { _59[0], _59[1] } }; float _60[2][2] = { { _54[0], _54[1] }, { _59[0], _59[1] } };
float _61[2][2][2] = { { { _49[0][0], _49[0][1] }, { _49[1][0], _49[1][1] } }, { { _60[0][0], _60[0][1] }, { _60[1][0], _60[1][1] } } }; float _61[2][2][2] = { { { _49[0][0], _49[0][1] }, { _49[1][0], _49[1][1] } }, { { _60[0][0], _60[0][1] }, { _60[1][0], _60[1][1] } } };
float d[2][2][2]; float d[2][2][2];
spvArrayCopyFromStackToStack3(d.elements, _61); spvArrayCopyFromStackToStack3(d, _61);
float e[2][2][2]; float e[2][2][2];
spvArrayCopyFromStackToStack3(e.elements, d); spvArrayCopyFromStackToStack3(e, d);
o.b = e[1][0][1]; o.b = e[1][0][1];
} }

View File

@ -0,0 +1,100 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
constant float4 _20[2] = { float4(10.0), float4(20.0) };
struct main0_out
{
float4 gl_Position [[position]];
};
struct main0_in
{
float4 vInput0 [[attribute(0)]];
float4 vInput1 [[attribute(1)]];
};
template<typename T, uint A>
inline void spvArrayCopyFromConstantToStack1(thread T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
inline void spvArrayCopyFromConstantToThreadGroup1(threadgroup T (&dst)[A], constant T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
inline void spvArrayCopyFromStackToStack1(thread T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
inline void spvArrayCopyFromStackToThreadGroup1(threadgroup T (&dst)[A], thread const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
inline void spvArrayCopyFromThreadGroupToStack1(thread T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
template<typename T, uint A>
inline void spvArrayCopyFromThreadGroupToThreadGroup1(threadgroup T (&dst)[A], threadgroup const T (&src)[A])
{
for (uint i = 0; i < A; i++)
{
dst[i] = src[i];
}
}
static inline __attribute__((always_inline))
void test(thread float4 (&SPIRV_Cross_return_value)[2])
{
spvArrayCopyFromConstantToStack1(SPIRV_Cross_return_value, _20);
}
static inline __attribute__((always_inline))
void test2(thread float4 (&SPIRV_Cross_return_value)[2], thread float4& vInput0, thread float4& vInput1)
{
float4 foobar[2];
foobar[0] = vInput0;
foobar[1] = vInput1;
spvArrayCopyFromStackToStack1(SPIRV_Cross_return_value, foobar);
}
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
float4 _42[2];
test(_42);
float4 _44[2];
test2(_44, in.vInput0, in.vInput1);
out.gl_Position = _42[0] + _44[1];
return out;
}

View File

@ -0,0 +1,22 @@
#version 310 es
layout(location = 0) in vec4 vInput0;
layout(location = 1) in vec4 vInput1;
vec4[2] test()
{
return vec4[](vec4(10.0), vec4(20.0));
}
vec4[2] test2()
{
vec4 foobar[2];
foobar[0] = vInput0;
foobar[1] = vInput1;
return foobar;
}
void main()
{
gl_Position = test()[0] + test2()[1];
}

View File

@ -6784,9 +6784,9 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageCla
SPIRV_CROSS_THROW("Unknown storage class used for copying arrays."); SPIRV_CROSS_THROW("Unknown storage class used for copying arrays.");
// Pass internal array of spvUnsafeArray<> into wrapper functions // Pass internal array of spvUnsafeArray<> into wrapper functions
if (lhs_thread) if (lhs_thread && !msl_options.force_native_arrays)
statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ".elements, ", to_expression(rhs_id), ");"); statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ".elements, ", to_expression(rhs_id), ");");
else if (rhs_thread) else if (rhs_thread && !msl_options.force_native_arrays)
statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ".elements);"); statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ".elements);");
else else
statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ");"); statement("spvArrayCopy", tag, type.array.size(), "(", lhs, ", ", to_expression(rhs_id), ");");
@ -7236,11 +7236,31 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &)
auto &type = get<SPIRType>(func.return_type); auto &type = get<SPIRType>(func.return_type);
decl += func_type_decl(type); if (!type.array.empty() && msl_options.force_native_arrays)
{
// We cannot return native arrays in MSL, so "return" through an out variable.
decl += "void";
}
else
{
decl += func_type_decl(type);
}
decl += " "; decl += " ";
decl += to_name(func.self); decl += to_name(func.self);
decl += "("; decl += "(";
if (!type.array.empty() && msl_options.force_native_arrays)
{
// 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)