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 <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
|
||||||
@ -9,6 +11,12 @@ struct Foobar
|
|||||||
float b;
|
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
|
struct main0_in
|
||||||
{
|
{
|
||||||
int index [[user(locn0)]];
|
int index [[user(locn0)]];
|
||||||
@ -19,6 +27,13 @@ struct main0_out
|
|||||||
float4 FragColor [[color(0)]];
|
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]])
|
fragment main0_out main0(main0_in in [[stage_in]])
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
#include <metal_stdlib>
|
#include <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
|
||||||
@ -9,6 +11,9 @@ struct Foo
|
|||||||
float b;
|
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
|
struct main0_in
|
||||||
{
|
{
|
||||||
int line [[user(locn0)]];
|
int line [[user(locn0)]];
|
||||||
@ -19,6 +24,13 @@ struct main0_out
|
|||||||
float4 FragColor [[color(0)]];
|
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]])
|
fragment main0_out main0(main0_in in [[stage_in]])
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
using namespace metal;
|
using namespace metal;
|
||||||
|
|
||||||
|
constant float4 _20[2] = {float4(10.0), float4(20.0)};
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
float4 vInput1 [[attribute(1)]];
|
float4 vInput1 [[attribute(1)]];
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
#include <metal_stdlib>
|
#include <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
|
||||||
@ -9,11 +11,20 @@ struct D
|
|||||||
float b;
|
float b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constant float4 _14[4] = {float4(0.0), float4(0.0), float4(0.0), float4(0.0)};
|
||||||
|
|
||||||
struct main0_out
|
struct main0_out
|
||||||
{
|
{
|
||||||
float FragColor [[color(0)]];
|
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()
|
fragment main0_out main0()
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
|
@ -11,6 +11,12 @@ struct Foobar
|
|||||||
float b;
|
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
|
struct main0_in
|
||||||
{
|
{
|
||||||
int index [[user(locn0)]];
|
int index [[user(locn0)]];
|
||||||
@ -21,6 +27,13 @@ struct main0_out
|
|||||||
float4 FragColor [[color(0)]];
|
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)
|
float4 resolve(thread const Foobar& f)
|
||||||
{
|
{
|
||||||
return float4(f.a + f.b);
|
return float4(f.a + f.b);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
#include <metal_stdlib>
|
#include <metal_stdlib>
|
||||||
#include <simd/simd.h>
|
#include <simd/simd.h>
|
||||||
|
|
||||||
@ -9,6 +11,9 @@ struct Foo
|
|||||||
float b;
|
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
|
struct main0_in
|
||||||
{
|
{
|
||||||
int line [[user(locn0)]];
|
int line [[user(locn0)]];
|
||||||
@ -19,6 +24,13 @@ struct main0_out
|
|||||||
float4 FragColor [[color(0)]];
|
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]])
|
fragment main0_out main0(main0_in in [[stage_in]])
|
||||||
{
|
{
|
||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
using namespace metal;
|
using namespace metal;
|
||||||
|
|
||||||
|
constant float4 _20[2] = {float4(10.0), float4(20.0)};
|
||||||
|
|
||||||
struct main0_in
|
struct main0_in
|
||||||
{
|
{
|
||||||
float4 vInput1 [[attribute(1)]];
|
float4 vInput1 [[attribute(1)]];
|
||||||
@ -25,7 +27,7 @@ void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])
|
|||||||
|
|
||||||
void test(thread float4 (&SPIRV_Cross_return_value)[2])
|
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)
|
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.use_typed_initializer_list = true;
|
||||||
backend.native_row_major_matrix = false;
|
backend.native_row_major_matrix = false;
|
||||||
backend.flexible_member_array_supported = false;
|
backend.flexible_member_array_supported = false;
|
||||||
|
backend.can_declare_arrays_inline = false;
|
||||||
backend.can_return_array = false;
|
backend.can_return_array = false;
|
||||||
|
|
||||||
replace_illegal_names();
|
replace_illegal_names();
|
||||||
@ -913,7 +914,7 @@ void CompilerMSL::emit_custom_functions()
|
|||||||
|
|
||||||
case SPVFuncImplArrayCopy:
|
case SPVFuncImplArrayCopy:
|
||||||
statement("// Implementation of an array copy function to cover GLSL's ability to copy an array via "
|
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("template<typename T, uint N>");
|
||||||
statement("void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])");
|
statement("void spvArrayCopy(thread T (&dst)[N], thread const T (&src)[N])");
|
||||||
begin_scope();
|
begin_scope();
|
||||||
@ -1135,6 +1136,34 @@ void CompilerMSL::declare_undefined_values()
|
|||||||
statement("");
|
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()
|
void CompilerMSL::emit_resources()
|
||||||
{
|
{
|
||||||
// Output non-interface structs. These include local function structs
|
// Output non-interface structs. These include local function structs
|
||||||
@ -1171,6 +1200,7 @@ void CompilerMSL::emit_resources()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_constant_arrays();
|
||||||
declare_undefined_values();
|
declare_undefined_values();
|
||||||
|
|
||||||
// Output interface structs.
|
// 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)
|
void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id)
|
||||||
{
|
{
|
||||||
// Assignment from an array initializer is fine.
|
// Assignment from an array initializer is fine.
|
||||||
if (ids[rhs_id].get_type() != TypeConstant)
|
statement("spvArrayCopy(", lhs, ", ", to_expression(rhs_id), ");");
|
||||||
statement("spvArrayCopy(", lhs, ", ", to_expression(rhs_id), ");");
|
|
||||||
else
|
|
||||||
statement(lhs, " = ", to_expression(rhs_id), ";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since MSL does not allow arrays to be copied via simple variable assignment,
|
// 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.
|
// Returns whether the struct assignment was emitted.
|
||||||
bool CompilerMSL::maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs)
|
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
|
// We only care about assignments of an entire array
|
||||||
auto &type = expression_type(id_rhs);
|
auto &type = expression_type(id_rhs);
|
||||||
if (type.array.size() == 0)
|
if (type.array.size() == 0)
|
||||||
return false;
|
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
|
// Ensure the LHS variable has been declared
|
||||||
auto *p_v_lhs = maybe_get_backing_variable(id_lhs);
|
auto *p_v_lhs = maybe_get_backing_variable(id_lhs);
|
||||||
if (p_v_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,
|
// 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.
|
// we must extract the result type directly from the Instruction, rather than the ID.
|
||||||
uint32_t id_rhs = args[1];
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +208,7 @@ protected:
|
|||||||
std::string to_qualifiers_glsl(uint32_t id) override;
|
std::string to_qualifiers_glsl(uint32_t id) override;
|
||||||
void replace_illegal_names() override;
|
void replace_illegal_names() override;
|
||||||
void declare_undefined_values() override;
|
void declare_undefined_values() override;
|
||||||
|
void declare_constant_arrays();
|
||||||
bool is_non_native_row_major_matrix(uint32_t id) override;
|
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;
|
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;
|
std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type) override;
|
||||||
|
Loading…
Reference in New Issue
Block a user