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:
parent
4739d16e98
commit
168e46fdf9
@ -45,6 +45,18 @@ struct image2DBase
|
|||||||
typedef image2DBase<glm::vec4> image2D;
|
typedef image2DBase<glm::vec4> image2D;
|
||||||
typedef image2DBase<glm::ivec4> iimage2D;
|
typedef image2DBase<glm::ivec4> iimage2D;
|
||||||
typedef image2DBase<glm::uvec4> uimage2D;
|
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
|
#endif
|
||||||
|
38
reference/shaders/comp/composite-construct.comp
Normal file
38
reference/shaders/comp/composite-construct.comp
Normal file
@ -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;
|
mat3x2 m3;
|
||||||
layout(row_major) mat2 m4;
|
layout(row_major) mat2 m4;
|
||||||
layout(row_major) mat2 m5[9];
|
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;
|
layout(row_major) mat3x2 m7;
|
||||||
float array[];
|
float array[];
|
||||||
} ssbo_430;
|
} ssbo_430;
|
||||||
|
40
shaders/comp/composite-construct.comp
Normal file
40
shaders/comp/composite-construct.comp
Normal file
@ -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);
|
add_resource_name(var.self);
|
||||||
|
|
||||||
auto instance_name = to_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);
|
statement_no_indent("#define ", instance_name, " __res->", instance_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ void CompilerCPP::emit_resources()
|
|||||||
if (var.storage == StorageClassWorkgroup)
|
if (var.storage == StorageClassWorkgroup)
|
||||||
emit_shared(var);
|
emit_shared(var);
|
||||||
else
|
else
|
||||||
statement(variable_decl(var), ";");
|
statement(CompilerGLSL::variable_decl(var), ";");
|
||||||
emitted = true;
|
emitted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,6 +279,7 @@ string CompilerCPP::compile()
|
|||||||
backend.shared_is_implied = true;
|
backend.shared_is_implied = true;
|
||||||
backend.flexible_member_array_supported = false;
|
backend.flexible_member_array_supported = false;
|
||||||
backend.explicit_struct_type = true;
|
backend.explicit_struct_type = true;
|
||||||
|
backend.use_initializer_list = true;
|
||||||
|
|
||||||
uint32_t pass_count = 0;
|
uint32_t pass_count = 0;
|
||||||
do
|
do
|
||||||
@ -347,39 +348,6 @@ void CompilerCPP::emit_c_linkage()
|
|||||||
end_scope();
|
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)
|
void CompilerCPP::emit_function_prototype(SPIRFunction &func, uint64_t)
|
||||||
{
|
{
|
||||||
local_variable_names = resource_names;
|
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;
|
bool constref = !type.pointer || arg.write_count == 0;
|
||||||
|
|
||||||
auto &var = get<SPIRVariable>(arg.id);
|
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()
|
void CompilerCPP::emit_header()
|
||||||
@ -431,6 +423,8 @@ void CompilerCPP::emit_header()
|
|||||||
statement("// This C++ shader is autogenerated by spirv-cross.");
|
statement("// This C++ shader is autogenerated by spirv-cross.");
|
||||||
statement("#include \"spirv_cross/internal_interface.hpp\"");
|
statement("#include \"spirv_cross/internal_interface.hpp\"");
|
||||||
statement("#include \"spirv_cross/external_interface.h\"");
|
statement("#include \"spirv_cross/external_interface.h\"");
|
||||||
|
// Needed to properly implement GLSL-style arrays.
|
||||||
|
statement("#include <array>");
|
||||||
statement("#include <stdint.h>");
|
statement("#include <stdint.h>");
|
||||||
statement("");
|
statement("");
|
||||||
statement("using namespace spirv_cross;");
|
statement("using namespace spirv_cross;");
|
||||||
|
@ -44,8 +44,8 @@ private:
|
|||||||
void emit_uniform(const SPIRVariable &var);
|
void emit_uniform(const SPIRVariable &var);
|
||||||
void emit_shared(const SPIRVariable &var);
|
void emit_shared(const SPIRVariable &var);
|
||||||
void emit_block_struct(SPIRType &type);
|
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::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||||
|
|
||||||
std::vector<std::string> resource_registrations;
|
std::vector<std::string> resource_registrations;
|
||||||
|
@ -1175,14 +1175,20 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c)
|
|||||||
if (!c.subconstants.empty())
|
if (!c.subconstants.empty())
|
||||||
{
|
{
|
||||||
// Handles Arrays and structures.
|
// 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)
|
for (auto &elem : c.subconstants)
|
||||||
{
|
{
|
||||||
res += constant_expression(get<SPIRConstant>(elem));
|
res += constant_expression(get<SPIRConstant>(elem));
|
||||||
if (&elem != &c.subconstants.back())
|
if (&elem != &c.subconstants.back())
|
||||||
res += ", ";
|
res += ", ";
|
||||||
}
|
}
|
||||||
res += ")";
|
|
||||||
|
res += backend.use_initializer_list ? " }" : ")";
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else if (c.columns() == 1)
|
else if (c.columns() == 1)
|
||||||
@ -1325,8 +1331,7 @@ string CompilerGLSL::declare_temporary(uint32_t result_type, uint32_t result_id)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The result_id has not been made into an expression yet, so use flags interface.
|
// 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),
|
return join(flags_to_precision_qualifiers_glsl(type, flags), variable_decl(type, to_name(result_id)), " = ");
|
||||||
type_to_array_glsl(type), " = ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2723,7 +2728,12 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||||||
forward = forward && should_forward(elems[i]);
|
forward = forward && should_forward(elems[i]);
|
||||||
|
|
||||||
auto &in_type = expression_type(elems[0]);
|
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)
|
if (splat)
|
||||||
{
|
{
|
||||||
@ -2733,12 +2743,28 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
|||||||
splat = false;
|
splat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto constructor_op = type_to_glsl_constructor(get<SPIRType>(result_type)) + "(";
|
string constructor_op;
|
||||||
if (splat)
|
if (backend.use_initializer_list && composite)
|
||||||
constructor_op += to_expression(elems[0]);
|
{
|
||||||
|
// 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
|
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);
|
emit_op(result_type, id, constructor_op, forward, false);
|
||||||
break;
|
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)
|
string CompilerGLSL::member_decl(const SPIRType &type, const SPIRType &membertype, uint32_t index)
|
||||||
{
|
{
|
||||||
uint64_t memberflags = 0;
|
uint64_t memberflags = 0;
|
||||||
@ -3640,7 +3671,7 @@ string CompilerGLSL::member_decl(const SPIRType &type, const SPIRType &membertyp
|
|||||||
memberflags = memb[index].decoration_flags;
|
memberflags = memb[index].decoration_flags;
|
||||||
|
|
||||||
return join(layout_for_member(type, index), flags_to_precision_qualifiers_glsl(membertype, memberflags),
|
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)
|
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 ";
|
direction = "out ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return join(direction, to_qualifiers_glsl(arg.id), type_to_glsl(type), " ", to_name(arg.id),
|
return join(direction, to_qualifiers_glsl(arg.id), variable_decl(type, to_name(arg.id)));
|
||||||
type_to_array_glsl(type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
|
||||||
{
|
{
|
||||||
// Ignore the pointer type since GLSL doesn't have pointers.
|
// Ignore the pointer type since GLSL doesn't have pointers.
|
||||||
auto &type = get<SPIRType>(variable.basetype);
|
auto &type = get<SPIRType>(variable.basetype);
|
||||||
auto res = join(to_qualifiers_glsl(variable.self), type_to_glsl(type), " ", to_name(variable.self),
|
auto res = join(to_qualifiers_glsl(variable.self), variable_decl(type, to_name(variable.self)));
|
||||||
type_to_array_glsl(type));
|
|
||||||
if (variable.initializer)
|
if (variable.initializer)
|
||||||
res += join(" = ", to_expression(variable.initializer));
|
res += join(" = ", to_expression(variable.initializer));
|
||||||
return res;
|
return res;
|
||||||
@ -3779,9 +3808,14 @@ string CompilerGLSL::pls_decl(const PlsRemap &var)
|
|||||||
|
|
||||||
string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
|
string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
|
||||||
{
|
{
|
||||||
|
if (type.array.empty())
|
||||||
|
return "";
|
||||||
|
|
||||||
string res;
|
string res;
|
||||||
for (auto &size : type.array)
|
for (size_t i = type.array.size(); i; i--)
|
||||||
{
|
{
|
||||||
|
auto &size = type.array[i - 1];
|
||||||
|
|
||||||
res += "[";
|
res += "[";
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
@ -4481,8 +4515,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
|||||||
{
|
{
|
||||||
auto flags = meta[tmp.second].decoration.decoration_flags;
|
auto flags = meta[tmp.second].decoration.decoration_flags;
|
||||||
auto &type = get<SPIRType>(tmp.first);
|
auto &type = get<SPIRType>(tmp.first);
|
||||||
statement(flags_to_precision_qualifiers_glsl(type, flags), type_to_glsl(type), " ", to_name(tmp.second),
|
statement(flags_to_precision_qualifiers_glsl(type, flags), variable_decl(type, to_name(tmp.second)), ";");
|
||||||
type_to_array_glsl(type), ";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SPIRBlock::ContinueBlockType continue_type = SPIRBlock::ContinueNone;
|
SPIRBlock::ContinueBlockType continue_type = SPIRBlock::ContinueNone;
|
||||||
|
@ -130,6 +130,7 @@ protected:
|
|||||||
virtual std::string constant_expression(const SPIRConstant &c);
|
virtual std::string constant_expression(const SPIRConstant &c);
|
||||||
virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
|
virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
|
||||||
virtual void emit_fixup();
|
virtual void emit_fixup();
|
||||||
|
virtual std::string variable_decl(const SPIRType &type, const std::string &name);
|
||||||
|
|
||||||
std::unique_ptr<std::ostringstream> buffer;
|
std::unique_ptr<std::ostringstream> buffer;
|
||||||
|
|
||||||
@ -208,6 +209,7 @@ protected:
|
|||||||
bool shared_is_implied = false;
|
bool shared_is_implied = false;
|
||||||
bool flexible_member_array_supported = true;
|
bool flexible_member_array_supported = true;
|
||||||
bool explicit_struct_type = false;
|
bool explicit_struct_type = false;
|
||||||
|
bool use_initializer_list = false;
|
||||||
} backend;
|
} backend;
|
||||||
|
|
||||||
void emit_struct(SPIRType &type);
|
void emit_struct(SPIRType &type);
|
||||||
|
Loading…
Reference in New Issue
Block a user