diff options
author | Paul Berry <[email protected]> | 2013-01-11 12:56:03 -0800 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-01-24 16:30:43 -0800 |
commit | 1ecd23dea944dbf4cdd2c6bfa8ce0e0e09de8239 (patch) | |
tree | 7748f7f6118ee549a097fe9b2c8f950181ec32f1 | |
parent | 88e4bfde2639568fabde6f5342e305e5689c6a27 (diff) |
glsl: Update lower_packed_varyings to handle varying structs.
This patch adds code to lower_packed_varyings to handle varyings of
type struct. Varying structs are currently packed in the most naive
possible way (in declaration order, with no gaps), so there is a
potential loss of runtime efficiency. In a later patch it would be
nice to replace this with a "flattening" approach (wherein a varying
struct is flattened to individual varyings corresponding to each of
its structure elements), so that the linker can align each structure
element independently. However, that would require a significantly
more complex implementation.
Reviewed-by: Jordan Justen <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
-rw-r--r-- | src/glsl/lower_packed_varyings.cpp | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/glsl/lower_packed_varyings.cpp b/src/glsl/lower_packed_varyings.cpp index 8f05752ed4b..8a40f5e72e5 100644 --- a/src/glsl/lower_packed_varyings.cpp +++ b/src/glsl/lower_packed_varyings.cpp @@ -70,6 +70,10 @@ * This lowering pass also packs flat floats, ints, and uints together, by * using ivec4 as the base type of flat "varyings", and using appropriate * casts to convert floats and uints into ints. + * + * This lowering pass also handles varyings whose type is a struct or an array + * of struct. Structs are packed in order and with no gaps, so there may be a + * performance penalty due to structure elements being double-parked. */ #include "glsl_symbol_table.h" @@ -274,10 +278,20 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, ir_variable *unpacked_var, const char *name) { - /* FINISHME: Support for "varying" records in GLSL 1.50. */ - assert(!rvalue->type->is_record()); - - if (rvalue->type->is_array()) { + if (rvalue->type->is_record()) { + for (unsigned i = 0; i < rvalue->type->length; i++) { + if (i != 0) + rvalue = rvalue->clone(this->mem_ctx, NULL); + const char *field_name = rvalue->type->fields.structure[i].name; + ir_dereference_record *dereference_record = new(this->mem_ctx) + ir_dereference_record(rvalue, field_name); + char *deref_name + = ralloc_asprintf(this->mem_ctx, "%s.%s", name, field_name); + fine_location = this->lower_rvalue(dereference_record, fine_location, + unpacked_var, deref_name); + } + return fine_location; + } else if (rvalue->type->is_array()) { /* Arrays are packed/unpacked by considering each array element in * sequence. */ |