summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2011-01-11 14:50:19 -0800
committerEric Anholt <eric@anholt.net>2011-01-11 14:50:19 -0800
commitc00bc13564e432c496aa685d7b3ca7c60165be02 (patch)
tree94c3414038327890f6feb6c113d826de8b761c8a /src
parent5acf94e95559879df13bfa854e081665fd58fb61 (diff)
glsl: Fix the lowering of variable array indexing to not lose write_masks.
Fixes glsl-complex-subscript on 965.
Diffstat (limited to 'src')
-rw-r--r--src/glsl/lower_variable_index_to_cond_assign.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/src/glsl/lower_variable_index_to_cond_assign.cpp b/src/glsl/lower_variable_index_to_cond_assign.cpp
index 5f0dd731135..7b4e4ad07cb 100644
--- a/src/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/src/glsl/lower_variable_index_to_cond_assign.cpp
@@ -42,6 +42,7 @@ struct assignment_generator
ir_instruction* base_ir;
ir_rvalue* array;
bool is_write;
+ unsigned int write_mask;
ir_variable* var;
assignment_generator()
@@ -54,14 +55,18 @@ struct assignment_generator
* underlying variable.
*/
void *mem_ctx = talloc_parent(base_ir);
- ir_rvalue *element =
+ ir_dereference *element =
new(mem_ctx) ir_dereference_array(this->array->clone(mem_ctx, NULL),
new(mem_ctx) ir_constant(i));
ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
- ir_assignment *assignment = (is_write)
- ? new(mem_ctx) ir_assignment(element, variable, condition)
- : new(mem_ctx) ir_assignment(variable, element, condition);
+ ir_assignment *assignment;
+ if (is_write) {
+ assignment = new(mem_ctx) ir_assignment(element, variable, condition,
+ write_mask);
+ } else {
+ assignment = new(mem_ctx) ir_assignment(variable, element, condition);
+ }
list->push_tail(assignment);
}
@@ -262,7 +267,7 @@ public:
}
ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
- ir_rvalue* value)
+ ir_assignment* orig_assign)
{
assert(is_array_or_matrix(orig_deref->array));
@@ -271,16 +276,30 @@ public:
: orig_deref->array->type->matrix_columns;
void *const mem_ctx = talloc_parent(base_ir);
- ir_variable *var =
- new(mem_ctx) ir_variable(orig_deref->type, "dereference_array_value",
- ir_var_temporary);
- base_ir->insert_before(var);
- if (value) {
+ /* Temporary storage for either the result of the dereference of
+ * the array, or the RHS that's being assigned into the
+ * dereference of the array.
+ */
+ ir_variable *var;
+
+ if (orig_assign) {
+ var = new(mem_ctx) ir_variable(orig_assign->rhs->type,
+ "dereference_array_value",
+ ir_var_temporary);
+ base_ir->insert_before(var);
+
ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var);
- ir_assignment *assign = new(mem_ctx) ir_assignment(lhs, value, NULL);
+ ir_assignment *assign = new(mem_ctx) ir_assignment(lhs,
+ orig_assign->rhs,
+ NULL);
base_ir->insert_before(assign);
+ } else {
+ var = new(mem_ctx) ir_variable(orig_deref->type,
+ "dereference_array_value",
+ ir_var_temporary);
+ base_ir->insert_before(var);
}
/* Store the index to a temporary to avoid reusing its tree. */
@@ -298,7 +317,12 @@ public:
ag.array = orig_deref->array;
ag.base_ir = base_ir;
ag.var = var;
- ag.is_write = !!value;
+ if (orig_assign) {
+ ag.is_write = true;
+ ag.write_mask = orig_assign->write_mask;
+ } else {
+ ag.is_write = false;
+ }
switch_generator sg(ag, index, 4, 4);
@@ -331,7 +355,7 @@ public:
ir_dereference_array *orig_deref = ir->lhs->as_dereference_array();
if (needs_lowering(orig_deref)) {
- convert_dereference_array(orig_deref, ir->rhs);
+ convert_dereference_array(orig_deref, ir);
ir->remove();
this->progress = true;
}