aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/lower_packed_varyings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/lower_packed_varyings.cpp')
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp28
1 files changed, 21 insertions, 7 deletions
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index 9e7f274b7..8a40f5e72 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/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"
@@ -135,8 +139,8 @@ private:
ir_variable **packed_varyings;
/**
- * Type of varying which is being lowered in this pass (either ir_var_in or
- * ir_var_out).
+ * Type of varying which is being lowered in this pass (either
+ * ir_var_shader_in or ir_var_shader_out).
*/
const ir_variable_mode mode;
@@ -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.
*/
@@ -336,7 +350,7 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue,
unpacked_var, name));
ir_swizzle *swizzle = new(this->mem_ctx)
ir_swizzle(packed_deref, swizzle_values, components);
- if (this->mode == ir_var_out) {
+ if (this->mode == ir_var_shader_out) {
ir_assignment *assignment
= this->bitwise_assign_pack(swizzle, rvalue);
this->main_instructions->push_tail(assignment);