glsl: Use array deref for access to vector components
We've assumed that we could lower per-component vector access from vec[i] = scalar to vec = ir_triop_vector_insert(vec, scalar, i) but with SSBOs (and compute shader SLM and tesselation outputs) this is no longer valid. If a vector is "externally visible", multiple threads can write independent components simultaneously. With lowering to ir_triop_vector_insert, each thread read the entire vector, changes one component, then writes out the entire vector. This is racy. Instead of generating a ir_binop_vector_extract when we see v[i], we generate ir_dereference_array. We then add a lowering pass to lower the ir_dereference_array to ir_binop_vector_extract for rvalues and for to vector_insert for lvalues in a separate lowering pass. The resulting IR is the same as before, but we now have a window between ast->ir conversion and the lowering pass where v[i] appears in the IR as an array deref. This lets us run lowering passes that lower the vector access to I/O (eg for SSBO load/store) before we lower the per-component access to full vector writes. Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> Signed-off-by: Kristian Høgsberg Kristensen <krh@bitplanet.net>
This commit is contained in:
@@ -256,18 +256,10 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
|
||||
actual->variable_referenced()->name);
|
||||
return false;
|
||||
} else if (!actual->is_lvalue()) {
|
||||
/* Even though ir_binop_vector_extract is not an l-value, let it
|
||||
* slop through. generate_call will handle it correctly.
|
||||
*/
|
||||
ir_expression *const expr = ((ir_rvalue *) actual)->as_expression();
|
||||
if (expr == NULL
|
||||
|| expr->operation != ir_binop_vector_extract
|
||||
|| !expr->operands[0]->is_lvalue()) {
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"function parameter '%s %s' is not an lvalue",
|
||||
mode, formal->name);
|
||||
return false;
|
||||
}
|
||||
_mesa_glsl_error(&loc, state,
|
||||
"function parameter '%s %s' is not an lvalue",
|
||||
mode, formal->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,12 +368,8 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type,
|
||||
|
||||
ir_rvalue *lhs = actual;
|
||||
if (expr != NULL && expr->operation == ir_binop_vector_extract) {
|
||||
rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert,
|
||||
expr->operands[0]->type,
|
||||
expr->operands[0]->clone(mem_ctx, NULL),
|
||||
rhs,
|
||||
expr->operands[1]->clone(mem_ctx, NULL));
|
||||
lhs = expr->operands[0]->clone(mem_ctx, NULL);
|
||||
lhs == new(mem_ctx) ir_dereference_array(expr->operands[0]->clone(mem_ctx, NULL),
|
||||
expr->operands[1]->clone(mem_ctx, NULL));
|
||||
}
|
||||
|
||||
ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs);
|
||||
|
||||
Reference in New Issue
Block a user