mirror of
https://github.com/KhronosGroup/SPIRV-Cross.git
synced 2024-11-15 00:11:06 +00:00
MSL cannot declare inline arrays except in certain cases.
This commit is contained in:
parent
156dd905fd
commit
1a9c960058
@ -1,3 +1,5 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
@ -9,6 +11,12 @@ struct Foobar
|
||||
float b;
|
||||
};
|
||||
|
||||
constant float4 _37[3] = {float4(1.0), float4(2.0), float4(3.0)};
|
||||
constant float4 _49[2] = {float4(1.0), float4(2.0)};
|
||||
constant float4 _54[2] = {float4(8.0), float4(10.0)};
|
||||
constant float4 _55[2][2] = {{float4(1.0), float4(2.0)}, {float4(8.0), float4(10.0)}};
|
||||
constant Foobar _75[2] = {{10.0, 40.0}, {90.0, 70.0}};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int index [[user(locn0)]];
|
||||
@ -19,6 +27,13 @@ struct main0_out
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
for (uint i = 0; i < N; dst[i] = src[i], i++);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
@ -9,6 +11,9 @@ struct Foo
|
||||
float b;
|
||||
};
|
||||
|
||||
constant float _16[4] = {1.0, 4.0, 3.0, 2.0};
|
||||
constant Foo _28[2] = {{10.0, 20.0}, {30.0, 40.0}};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int line [[user(locn0)]];
|
||||
@ -19,6 +24,13 @@ struct main0_out
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
for (uint i = 0; i < N; dst[i] = src[i], i++);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constant float4 _20[2] = {float4(10.0), float4(20.0)};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vInput1 [[attribute(1)]];
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
@ -9,11 +11,20 @@ struct D
|
||||
float b;
|
||||
};
|
||||
|
||||
constant float4 _14[4] = {float4(0.0), float4(0.0), float4(0.0), float4(0.0)};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
for (uint i = 0; i < N; dst[i] = src[i], i++);
|
||||
}
|
||||
|
||||
fragment main0_out main0()
|
||||
{
|
||||
main0_out out = {};
|
||||
|
@ -11,6 +11,12 @@ struct Foobar
|
||||
float b;
|
||||
};
|
||||
|
||||
constant float4 _37[3] = {float4(1.0), float4(2.0), float4(3.0)};
|
||||
constant float4 _49[2] = {float4(1.0), float4(2.0)};
|
||||
constant float4 _54[2] = {float4(8.0), float4(10.0)};
|
||||
constant float4 _55[2][2] = {{float4(1.0), float4(2.0)}, {float4(8.0), float4(10.0)}};
|
||||
constant Foobar _75[2] = {{10.0, 40.0}, {90.0, 70.0}};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int index [[user(locn0)]];
|
||||
@ -21,6 +27,13 @@ struct main0_out
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
for (uint i = 0; i < N; dst[i] = src[i], i++);
|
||||
}
|
||||
|
||||
float4 resolve(thread const Foobar& f)
|
||||
{
|
||||
return float4(f.a + f.b);
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
@ -9,6 +11,9 @@ struct Foo
|
||||
float b;
|
||||
};
|
||||
|
||||
constant float _16[4] = {1.0, 4.0, 3.0, 2.0};
|
||||
constant Foo _28[2] = {{10.0, 20.0}, {30.0, 40.0}};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int line [[user(locn0)]];
|
||||
@ -19,6 +24,13 @@ struct main0_out
|
||||
float4 FragColor [[color(0)]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
for (uint i = 0; i < N; dst[i] = src[i], i++);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
using namespace metal;
|
||||
|
||||
constant float4 _20[2] = {float4(10.0), float4(20.0)};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 vInput1 [[attribute(1)]];
|
||||
@ -16,7 +18,7 @@ struct main0_out
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
// Implementation of an array copy function to cover GLSL's ability to copy an array via assignment.
|
||||
template<typename T, uint N>
|
||||
void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
{
|
||||
@ -25,7 +27,7 @@ void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
||||
|
||||
void test(thread float4 (&SPIRV_Cross_return_value)[2])
|
||||
{
|
||||
SPIRV_Cross_return_value = {float4(10.0), float4(20.0)};
|
||||
spvArrayCopy(SPIRV_Cross_return_value, _20);
|
||||
}
|
||||
|
||||
void test2(thread float4 (&SPIRV_Cross_return_value)[2], thread float4& vInput0, thread float4& vInput1)
|
||||
|
@ -72,6 +72,7 @@ string CompilerMSL::compile()
|
||||
backend.use_typed_initializer_list = true;
|
||||
backend.native_row_major_matrix = false;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.can_declare_arrays_inline = false;
|
||||
backend.can_return_array = false;
|
||||
|
||||
replace_illegal_names();
|
||||
@ -913,7 +914,7 @@ void CompilerMSL::emit_custom_functions()
|
||||
|
||||
case SPVFuncImplArrayCopy:
|
||||
statement("// Implementation of an array copy function to cover GLSL's ability to copy an array via "
|
||||
"assignment. ");
|
||||
"assignment.");
|
||||
statement("template<typename T, uint N>");
|
||||
statement("void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])");
|
||||
begin_scope();
|
||||
@ -1135,6 +1136,34 @@ void CompilerMSL::declare_undefined_values()
|
||||
statement("");
|
||||
}
|
||||
|
||||
void CompilerMSL::declare_constant_arrays()
|
||||
{
|
||||
// MSL cannot declare arrays inline (except when declaring a variable), so we must move them out to
|
||||
// global constants directly, so we are able to use constants as variable expressions.
|
||||
bool emitted = false;
|
||||
|
||||
for (auto &id : ids)
|
||||
{
|
||||
if (id.get_type() == TypeConstant)
|
||||
{
|
||||
auto &c = id.get<SPIRConstant>();
|
||||
if (c.specialization)
|
||||
continue;
|
||||
|
||||
auto &type = get<SPIRType>(c.constant_type);
|
||||
if (!type.array.empty())
|
||||
{
|
||||
auto name = to_name(c.self);
|
||||
statement("constant ", variable_decl(type, name), " = ", constant_expression(c), ";");
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (emitted)
|
||||
statement("");
|
||||
}
|
||||
|
||||
void CompilerMSL::emit_resources()
|
||||
{
|
||||
// Output non-interface structs. These include local function structs
|
||||
@ -1171,6 +1200,7 @@ void CompilerMSL::emit_resources()
|
||||
}
|
||||
}
|
||||
|
||||
declare_constant_arrays();
|
||||
declare_undefined_values();
|
||||
|
||||
// Output interface structs.
|
||||
@ -1747,10 +1777,7 @@ bool CompilerMSL::maybe_emit_input_struct_assignment(uint32_t id_lhs, uint32_t i
|
||||
void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
|
||||
{
|
||||
// Assignment from an array initializer is fine.
|
||||
if (ids[rhs_id].get_type() != TypeConstant)
|
||||
statement("spvArrayCopy(", lhs, ", ", to_expression(rhs_id), ");");
|
||||
else
|
||||
statement(lhs, " = ", to_expression(rhs_id), ";");
|
||||
statement("spvArrayCopy(", lhs, ", ", to_expression(rhs_id), ");");
|
||||
}
|
||||
|
||||
// Since MSL does not allow arrays to be copied via simple variable assignment,
|
||||
@ -1759,15 +1786,23 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
|
||||
// Returns whether the struct assignment was emitted.
|
||||
bool CompilerMSL::maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs)
|
||||
{
|
||||
// Assignment from an array initializer is fine.
|
||||
if (ids[id_rhs].get_type() == TypeConstant)
|
||||
return false;
|
||||
|
||||
// We only care about assignments of an entire array
|
||||
auto &type = expression_type(id_rhs);
|
||||
if (type.array.size() == 0)
|
||||
return false;
|
||||
|
||||
auto *var = maybe_get<SPIRVariable>(id_lhs);
|
||||
if (ids[id_rhs].get_type() == TypeConstant && var && var->deferred_declaration)
|
||||
{
|
||||
// Special case, if we end up declaring a variable when assigning the constant array,
|
||||
// we can avoid the copy by directly assigning the constant expression.
|
||||
// This is likely necessary to be able to use a variable as a true look-up table, as it is unlikely
|
||||
// the compiler will be able to optimize the spvArrayCopy() into a constant LUT.
|
||||
// After a variable has been declared, we can no longer assign constant arrays in MSL unfortunately.
|
||||
statement(to_expression(id_lhs), " = ", constant_expression(get<SPIRConstant>(id_rhs)), ";");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure the LHS variable has been declared
|
||||
auto *p_v_lhs = maybe_get_backing_variable(id_lhs);
|
||||
if (p_v_lhs)
|
||||
@ -3566,11 +3601,24 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
|
||||
// Get the result type of the RHS. Since this is run as a pre-processing stage,
|
||||
// we must extract the result type directly from the Instruction, rather than the ID.
|
||||
uint32_t id_rhs = args[1];
|
||||
uint32_t type_id_rhs = result_types[id_rhs];
|
||||
if ((compiler.ids[id_rhs].get_type() != TypeConstant) && type_id_rhs &&
|
||||
compiler.is_array(compiler.get<SPIRType>(type_id_rhs)))
|
||||
return SPVFuncImplArrayCopy;
|
||||
|
||||
const SPIRType *type = nullptr;
|
||||
if (compiler.ids[id_rhs].get_type() != TypeNone)
|
||||
{
|
||||
// Could be a constant, or similar.
|
||||
type = &compiler.expression_type(id_rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Or ... an expression.
|
||||
if (result_types[id_rhs] != 0)
|
||||
type = &compiler.get<SPIRType>(result_types[id_rhs]);
|
||||
}
|
||||
|
||||
if (type && compiler.is_array(*type))
|
||||
return SPVFuncImplArrayCopy;
|
||||
else
|
||||
return SPVFuncImplNone;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,7 @@ protected:
|
||||
std::string to_qualifiers_glsl(uint32_t id) override;
|
||||
void replace_illegal_names() override;
|
||||
void declare_undefined_values() override;
|
||||
void declare_constant_arrays();
|
||||
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) override;
|
||||
|
Loading…
Reference in New Issue
Block a user