Add support for loading flattened structs.

This commit is contained in:
Hans-Kristian Arntzen 2017-02-23 19:24:59 +01:00
parent 97350d32fd
commit fc80cd8cbf
6 changed files with 98 additions and 5 deletions

View File

@ -0,0 +1,22 @@
#version 100
precision mediump float;
precision highp int;
struct Inputs
{
vec4 a;
vec2 b;
};
varying vec4 Inputs_a;
varying vec2 Inputs_b;
void main()
{
Inputs v0 = Inputs(Inputs_a, Inputs_b);
Inputs v1 = Inputs(Inputs_a, Inputs_b);
vec4 a = Inputs_a;
vec4 b = Inputs_b.xxyy;
gl_FragData[0] = ((((v0.a + v0.b.xxyy) + v1.a) + v1.b.yyxx) + a) + b;
}

View File

@ -22,7 +22,11 @@ void main()
Output_a = vout.a;
Output_b = vout.b;
}
Output_a = s.a;
Output_b = s.b;
Output tmp = Output(Output_a, Output_b);
Output_a = tmp.a;
Output_b = tmp.b;
Output_a.x = 1.0;
Output_b.y = 1.0;
float c = Output_a.x;
}

View File

@ -0,0 +1,25 @@
#version 310 es
precision mediump float;
struct Inputs
{
vec4 a;
vec2 b;
};
layout(location = 0) in Inputs vin;
layout(location = 0) out vec4 FragColor;
void main()
{
// Read struct once.
Inputs v0 = vin;
// Read struct again.
Inputs v1 = vin;
// Read members individually.
vec4 a = vin.a;
vec4 b = vin.b.xxyy;
FragColor = v0.a + v0.b.xxyy + v1.a + v1.b.yyxx + a + b;
}

View File

@ -17,7 +17,17 @@ void main()
// Write whole struct again, checks for scoping.
vout = s;
// Read it back.
Output tmp = vout;
// Write elements individually.
vout.a = s.a;
vout.b = s.b;
vout.a = tmp.a;
vout.b = tmp.b;
// Write individual elements.
vout.a.x = 1.0;
vout.b.y = 1.0;
// Read individual elements.
float c = vout.a.x;
}

View File

@ -1760,6 +1760,10 @@ string CompilerGLSL::to_expression(uint32_t id)
var.deferred_declaration = false;
return variable_decl(var);
}
else if (flattened_structs.count(id))
{
return load_flattened_struct(var);
}
else
{
auto &dec = meta[var.self].decoration;
@ -3386,6 +3390,11 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
return expr;
}
string CompilerGLSL::to_flattened_struct_member(const SPIRType &type, uint32_t index)
{
return sanitize_underscores(join(to_name(type.self), "_", to_member_name(type, index)));
}
string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type,
bool *out_need_transpose)
{
@ -3404,6 +3413,8 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
{
auto chain = access_chain_internal(base, indices, count, false, true).substr(1);
auto &type = get<SPIRType>(get<SPIRVariable>(base).basetype);
if (out_need_transpose)
*out_need_transpose = false;
return sanitize_underscores(join(to_name(type.self), "_", chain));
}
else
@ -3412,6 +3423,25 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
}
}
string CompilerGLSL::load_flattened_struct(SPIRVariable &var)
{
auto expr = type_to_glsl_constructor(get<SPIRType>(var.basetype));
expr += '(';
auto &type = get<SPIRType>(var.basetype);
for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
{
if (i)
expr += ", ";
// Flatten the varyings.
// Apply name transformation for flattened I/O blocks.
expr += to_flattened_struct_member(type, i);
}
expr += ')';
return expr;
}
void CompilerGLSL::store_flattened_struct(SPIRVariable &var, uint32_t value)
{
// We're trying to store a structure which has been flattened.
@ -3431,7 +3461,7 @@ void CompilerGLSL::store_flattened_struct(SPIRVariable &var, uint32_t value)
// Apply name transformation for flattened I/O blocks.
auto lhs = sanitize_underscores(join(to_name(type.self), "_", to_member_name(type, i)));
rhs = access_chain_internal(var.self, &i, 1, true);
rhs = join(to_name(var.self), ".", to_member_name(type, i));
statement(lhs, " = ", rhs, ";");
}
end_scope();

View File

@ -387,6 +387,8 @@ protected:
std::unordered_set<uint32_t> flattened_buffer_blocks;
std::unordered_set<uint32_t> flattened_structs;
std::string load_flattened_struct(SPIRVariable &var);
std::string to_flattened_struct_member(const SPIRType &type, uint32_t index);
void store_flattened_struct(SPIRVariable &var, uint32_t value);
// Usage tracking. If a temporary is used more than once, use the temporary instead to