glsl: Don't lower vector derefs for SSBOs, UBOs, and shared

All of these are backed by some sort of memory so if you have multiple
threads writing to different components of the same vector at the same
time, the load-vec-store pattern that GLSL IR emits won't work.  This
shouldn't affect any drivers today as they all call GLSL IR lowering
which lowers access to these variables to index+offset intrinsics before
we get to this point.  However, NIR will start handling the derefs
itself and won't want the lowering.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
This commit is contained in:
Jason Ekstrand 2019-03-11 14:53:31 -05:00 committed by Jason Ekstrand
parent 3c11fc7654
commit 8f3ab8aa78
1 changed files with 21 additions and 0 deletions

View File

@ -63,6 +63,16 @@ vector_deref_visitor::visit_enter(ir_assignment *ir)
if (!deref->array->type->is_vector())
return ir_rvalue_enter_visitor::visit_enter(ir);
/* SSBOs and shared variables are backed by memory and may be accessed by
* multiple threads simultaneously. It's not safe to lower a single
* component store to a load-vec-store because it may race with writes to
* other components.
*/
ir_variable *var = deref->variable_referenced();
if (var->data.mode == ir_var_shader_storage ||
var->data.mode == ir_var_shader_shared)
return ir_rvalue_enter_visitor::visit_enter(ir);
ir_rvalue *const new_lhs = deref->array;
void *mem_ctx = ralloc_parent(ir);
@ -150,6 +160,17 @@ vector_deref_visitor::handle_rvalue(ir_rvalue **rv)
if (!deref->array->type->is_vector())
return;
/* Back-ends need to be able to handle derefs on vectors for SSBOs, UBOs,
* and shared variables. They have to handle it for writes anyway so we
* may as well require it for reads.
*/
ir_variable *var = deref->variable_referenced();
if (var && (var->data.mode == ir_var_shader_storage ||
var->data.mode == ir_var_shader_shared ||
(var->data.mode == ir_var_uniform &&
var->get_interface_type())))
return;
void *mem_ctx = ralloc_parent(deref);
*rv = new(mem_ctx) ir_expression(ir_binop_vector_extract,
deref->array,