Use std::array in C++ backend.
Deals better with composite construction in C++ and also fixes a few bugs in GLSL backend with array-of-arrays.
This commit is contained in:
Родитель
4739d16e98
Коммит
168e46fdf9
|
@ -45,6 +45,18 @@ struct image2DBase
|
|||
typedef image2DBase<glm::vec4> image2D;
|
||||
typedef image2DBase<glm::ivec4> iimage2D;
|
||||
typedef image2DBase<glm::uvec4> uimage2D;
|
||||
|
||||
template <typename T>
|
||||
inline T imageLoad(const image2DBase<T> &image, glm::ivec2 coord)
|
||||
{
|
||||
return image.load(coord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void imageStore(image2DBase<T> &image, glm::ivec2 coord, const T &value)
|
||||
{
|
||||
image.store(coord, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#version 310 es
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
struct Composite
|
||||
{
|
||||
vec4 a[2];
|
||||
vec4 b[2];
|
||||
};
|
||||
|
||||
layout(binding = 0, std430) buffer SSBO0
|
||||
{
|
||||
vec4 as[];
|
||||
} _41;
|
||||
|
||||
layout(binding = 1, std430) buffer SSBO1
|
||||
{
|
||||
vec4 bs[];
|
||||
} _55;
|
||||
|
||||
vec4 summe(vec4 values[3][2])
|
||||
{
|
||||
return (((values[0][0] + values[2][1]) + values[0][1]) + values[1][0]);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 values[2] = vec4[](_41.as[gl_GlobalInvocationID.x], _55.bs[gl_GlobalInvocationID.x]);
|
||||
vec4 const_values[2] = vec4[](vec4(10.0), vec4(30.0));
|
||||
vec4 copy_values[2] = const_values;
|
||||
vec4 copy_values2[2] = values;
|
||||
vec4 param[3][2] = vec4[][](values, copy_values, copy_values2);
|
||||
_41.as[gl_GlobalInvocationID.x] = summe(param);
|
||||
Composite c = Composite(values, copy_values);
|
||||
float arrayofarray[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
|
||||
float b = 10.0;
|
||||
float values_scalar[4] = float[](b, b, b, b);
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ layout(binding = 1, std430) buffer SSBO1
|
|||
mat3x2 m3;
|
||||
layout(row_major) mat2 m4;
|
||||
layout(row_major) mat2 m5[9];
|
||||
layout(row_major) mat2x3 m6[2][4];
|
||||
layout(row_major) mat2x3 m6[4][2];
|
||||
layout(row_major) mat3x2 m7;
|
||||
float array[];
|
||||
} ssbo_430;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#version 310 es
|
||||
layout(local_size_x = 1) in;
|
||||
|
||||
layout(std430, binding = 0) buffer SSBO0
|
||||
{
|
||||
vec4 as[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 1) buffer SSBO1
|
||||
{
|
||||
vec4 bs[];
|
||||
};
|
||||
|
||||
vec4 summe(vec4 values[3][2])
|
||||
{
|
||||
return values[0][0] + values[2][1] + values[0][1] + values[1][0];
|
||||
}
|
||||
|
||||
struct Composite
|
||||
{
|
||||
vec4 a[2];
|
||||
vec4 b[2];
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 values[2] = vec4[](as[gl_GlobalInvocationID.x], bs[gl_GlobalInvocationID.x]);
|
||||
vec4 const_values[2] = vec4[](vec4(10.0), vec4(30.0));
|
||||
vec4 copy_values[2];
|
||||
copy_values = const_values;
|
||||
vec4 copy_values2[2] = values;
|
||||
as[gl_GlobalInvocationID.x] = summe(vec4[][](values, copy_values, copy_values2));
|
||||
|
||||
Composite c = Composite(values, copy_values);
|
||||
|
||||
float arrayofarray[2][3] = float[][](float[](1.0, 1.0, 1.0), float[](2.0, 2.0, 2.0));
|
||||
|
||||
float b = 10.0;
|
||||
float values_scalar[4] = float[](b, b, b, b);
|
||||
}
|
|
@ -67,7 +67,7 @@ void CompilerCPP::emit_shared(const SPIRVariable &var)
|
|||
add_resource_name(var.self);
|
||||
|
||||
auto instance_name = to_name(var.self);
|
||||
statement(variable_decl(var), ";");
|
||||
statement(CompilerGLSL::variable_decl(var), ";");
|
||||
statement_no_indent("#define ", instance_name, " __res->", instance_name);
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ void CompilerCPP::emit_resources()
|
|||
if (var.storage == StorageClassWorkgroup)
|
||||
emit_shared(var);
|
||||
else
|
||||
statement(variable_decl(var), ";");
|
||||
statement(CompilerGLSL::variable_decl(var), ";");
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +279,7 @@ string CompilerCPP::compile()
|
|||
backend.shared_is_implied = true;
|
||||
backend.flexible_member_array_supported = false;
|
||||
backend.explicit_struct_type = true;
|
||||
backend.use_initializer_list = true;
|
||||
|
||||
uint32_t pass_count = 0;
|
||||
do
|
||||
|
@ -347,39 +348,6 @@ void CompilerCPP::emit_c_linkage()
|
|||
end_scope();
|
||||
}
|
||||
|
||||
string CompilerCPP::constant_expression(const SPIRConstant &c)
|
||||
{
|
||||
if (!c.subconstants.empty())
|
||||
{
|
||||
// Handles Arrays and structures.
|
||||
string res = "{";
|
||||
for (auto &elem : c.subconstants)
|
||||
{
|
||||
res += constant_expression(get<SPIRConstant>(elem));
|
||||
if (&elem != &c.subconstants.back())
|
||||
res += ", ";
|
||||
}
|
||||
res += "}";
|
||||
return res;
|
||||
}
|
||||
else if (c.columns() == 1)
|
||||
{
|
||||
return constant_expression_vector(c, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
string res = "{";
|
||||
for (uint32_t col = 0; col < c.columns(); col++)
|
||||
{
|
||||
res += constant_expression_vector(c, col);
|
||||
if (col + 1 < c.columns())
|
||||
res += ", ";
|
||||
}
|
||||
res += "}";
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerCPP::emit_function_prototype(SPIRFunction &func, uint64_t)
|
||||
{
|
||||
local_variable_names = resource_names;
|
||||
|
@ -423,7 +391,31 @@ string CompilerCPP::argument_decl(const SPIRFunction::Parameter &arg)
|
|||
bool constref = !type.pointer || arg.write_count == 0;
|
||||
|
||||
auto &var = get<SPIRVariable>(arg.id);
|
||||
return join(constref ? "const " : "", type_to_glsl(type), "& ", to_name(var.self), type_to_array_glsl(type));
|
||||
|
||||
string base = type_to_glsl(type);
|
||||
for (auto &array : type.array)
|
||||
base = join("std::array<", base, ", ", array, ">");
|
||||
|
||||
return join(constref ? "const " : "", base, " &", to_name(var.self));
|
||||
}
|
||||
|
||||
string CompilerCPP::variable_decl(const SPIRType &type, const string &name)
|
||||
{
|
||||
string base = type_to_glsl(type);
|
||||
bool runtime = false;
|
||||
for (auto &array : type.array)
|
||||
{
|
||||
if (array)
|
||||
base = join("std::array<", base, ", ", array, ">");
|
||||
else
|
||||
{
|
||||
// Avoid using runtime arrays with std::array since this is undefined.
|
||||
// Runtime arrays cannot be passed around as values, so this is fine.
|
||||
runtime = true;
|
||||
}
|
||||
}
|
||||
base += ' ';
|
||||
return base + name + (runtime ? "[1]" : "");
|
||||
}
|
||||
|
||||
void CompilerCPP::emit_header()
|
||||
|
@ -431,6 +423,8 @@ void CompilerCPP::emit_header()
|
|||
statement("// This C++ shader is autogenerated by spirv-cross.");
|
||||
statement("#include \"spirv_cross/internal_interface.hpp\"");
|
||||
statement("#include \"spirv_cross/external_interface.h\"");
|
||||
// Needed to properly implement GLSL-style arrays.
|
||||
statement("#include <array>");
|
||||
statement("#include <stdint.h>");
|
||||
statement("");
|
||||
statement("using namespace spirv_cross;");
|
||||
|
|
|
@ -44,8 +44,8 @@ private:
|
|||
void emit_uniform(const SPIRVariable &var);
|
||||
void emit_shared(const SPIRVariable &var);
|
||||
void emit_block_struct(SPIRType &type);
|
||||
std::string variable_decl(const SPIRType &type, const std::string &name) override;
|
||||
|
||||
std::string constant_expression(const SPIRConstant &c) override;
|
||||
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||
|
||||
std::vector<std::string> resource_registrations;
|
||||
|
|
|
@ -1175,14 +1175,20 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c)
|
|||
if (!c.subconstants.empty())
|
||||
{
|
||||
// Handles Arrays and structures.
|
||||
string res = type_to_glsl_constructor(get<SPIRType>(c.constant_type)) + "(";
|
||||
string res;
|
||||
if (backend.use_initializer_list)
|
||||
res = "{ ";
|
||||
else
|
||||
res = type_to_glsl_constructor(get<SPIRType>(c.constant_type)) + "(";
|
||||
|
||||
for (auto &elem : c.subconstants)
|
||||
{
|
||||
res += constant_expression(get<SPIRConstant>(elem));
|
||||
if (&elem != &c.subconstants.back())
|
||||
res += ", ";
|
||||
}
|
||||
res += ")";
|
||||
|
||||
res += backend.use_initializer_list ? " }" : ")";
|
||||
return res;
|
||||
}
|
||||
else if (c.columns() == 1)
|
||||
|
@ -1325,8 +1331,7 @@ string CompilerGLSL::declare_temporary(uint32_t result_type, uint32_t result_id)
|
|||
else
|
||||
{
|
||||
// The result_id has not been made into an expression yet, so use flags interface.
|
||||
return join(flags_to_precision_qualifiers_glsl(type, flags), type_to_glsl(type), " ", to_name(result_id),
|
||||
type_to_array_glsl(type), " = ");
|
||||
return join(flags_to_precision_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), " = ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2723,7 +2728,12 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||
forward = forward && should_forward(elems[i]);
|
||||
|
||||
auto &in_type = expression_type(elems[0]);
|
||||
bool splat = in_type.vecsize == 1 && in_type.columns == 1;
|
||||
auto &out_type = get<SPIRType>(result_type);
|
||||
|
||||
// Only splat if we have vector constructors.
|
||||
// Arrays and structs must be initialized properly in full.
|
||||
bool composite = !out_type.array.empty() || out_type.basetype == SPIRType::Struct;
|
||||
bool splat = in_type.vecsize == 1 && in_type.columns == 1 && !composite;
|
||||
|
||||
if (splat)
|
||||
{
|
||||
|
@ -2733,12 +2743,28 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||
splat = false;
|
||||
}
|
||||
|
||||
auto constructor_op = type_to_glsl_constructor(get<SPIRType>(result_type)) + "(";
|
||||
if (splat)
|
||||
constructor_op += to_expression(elems[0]);
|
||||
string constructor_op;
|
||||
if (backend.use_initializer_list && composite)
|
||||
{
|
||||
// Only use this path if we are building composites.
|
||||
// This path cannot be used for arithmetic.
|
||||
constructor_op += "{ ";
|
||||
if (splat)
|
||||
constructor_op += to_expression(elems[0]);
|
||||
else
|
||||
constructor_op += build_composite_combiner(elems, length);
|
||||
constructor_op += " }";
|
||||
}
|
||||
else
|
||||
constructor_op += build_composite_combiner(elems, length);
|
||||
constructor_op += ")";
|
||||
{
|
||||
constructor_op = type_to_glsl_constructor(get<SPIRType>(result_type)) + "(";
|
||||
if (splat)
|
||||
constructor_op += to_expression(elems[0]);
|
||||
else
|
||||
constructor_op += build_composite_combiner(elems, length);
|
||||
constructor_op += ")";
|
||||
}
|
||||
|
||||
emit_op(result_type, id, constructor_op, forward, false);
|
||||
break;
|
||||
}
|
||||
|
@ -3632,6 +3658,11 @@ void CompilerGLSL::add_member_name(SPIRType &type, uint32_t index)
|
|||
}
|
||||
}
|
||||
|
||||
string CompilerGLSL::variable_decl(const SPIRType &type, const std::string &name)
|
||||
{
|
||||
return join(type_to_glsl(type), " ", name, type_to_array_glsl(type));
|
||||
}
|
||||
|
||||
string CompilerGLSL::member_decl(const SPIRType &type, const SPIRType &membertype, uint32_t index)
|
||||
{
|
||||
uint64_t memberflags = 0;
|
||||
|
@ -3640,7 +3671,7 @@ string CompilerGLSL::member_decl(const SPIRType &type, const SPIRType &membertyp
|
|||
memberflags = memb[index].decoration_flags;
|
||||
|
||||
return join(layout_for_member(type, index), flags_to_precision_qualifiers_glsl(membertype, memberflags),
|
||||
type_to_glsl(membertype), " ", to_member_name(type, index), type_to_array_glsl(membertype));
|
||||
variable_decl(membertype, to_member_name(type, index)));
|
||||
}
|
||||
|
||||
const char *CompilerGLSL::flags_to_precision_qualifiers_glsl(const SPIRType &type, uint64_t flags)
|
||||
|
@ -3741,16 +3772,14 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
|
|||
direction = "out ";
|
||||
}
|
||||
|
||||
return join(direction, to_qualifiers_glsl(arg.id), type_to_glsl(type), " ", to_name(arg.id),
|
||||
type_to_array_glsl(type));
|
||||
return join(direction, to_qualifiers_glsl(arg.id), variable_decl(type, to_name(arg.id)));
|
||||
}
|
||||
|
||||
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
||||
{
|
||||
// Ignore the pointer type since GLSL doesn't have pointers.
|
||||
auto &type = get<SPIRType>(variable.basetype);
|
||||
auto res = join(to_qualifiers_glsl(variable.self), type_to_glsl(type), " ", to_name(variable.self),
|
||||
type_to_array_glsl(type));
|
||||
auto res = join(to_qualifiers_glsl(variable.self), variable_decl(type, to_name(variable.self)));
|
||||
if (variable.initializer)
|
||||
res += join(" = ", to_expression(variable.initializer));
|
||||
return res;
|
||||
|
@ -3779,9 +3808,14 @@ string CompilerGLSL::pls_decl(const PlsRemap &var)
|
|||
|
||||
string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
|
||||
{
|
||||
if (type.array.empty())
|
||||
return "";
|
||||
|
||||
string res;
|
||||
for (auto &size : type.array)
|
||||
for (size_t i = type.array.size(); i; i--)
|
||||
{
|
||||
auto &size = type.array[i - 1];
|
||||
|
||||
res += "[";
|
||||
if (size)
|
||||
{
|
||||
|
@ -4481,8 +4515,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||
{
|
||||
auto flags = meta[tmp.second].decoration.decoration_flags;
|
||||
auto &type = get<SPIRType>(tmp.first);
|
||||
statement(flags_to_precision_qualifiers_glsl(type, flags), type_to_glsl(type), " ", to_name(tmp.second),
|
||||
type_to_array_glsl(type), ";");
|
||||
statement(flags_to_precision_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), ";");
|
||||
}
|
||||
|
||||
SPIRBlock::ContinueBlockType continue_type = SPIRBlock::ContinueNone;
|
||||
|
|
|
@ -130,6 +130,7 @@ protected:
|
|||
virtual std::string constant_expression(const SPIRConstant &c);
|
||||
virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
|
||||
virtual void emit_fixup();
|
||||
virtual std::string variable_decl(const SPIRType &type, const std::string &name);
|
||||
|
||||
std::unique_ptr<std::ostringstream> buffer;
|
||||
|
||||
|
@ -208,6 +209,7 @@ protected:
|
|||
bool shared_is_implied = false;
|
||||
bool flexible_member_array_supported = true;
|
||||
bool explicit_struct_type = false;
|
||||
bool use_initializer_list = false;
|
||||
} backend;
|
||||
|
||||
void emit_struct(SPIRType &type);
|
||||
|
|
Загрузка…
Ссылка в новой задаче