From 8f3ab8aa7824a2f306b542a50b304675ce8f7e1a Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 11 Mar 2019 14:53:31 -0500 Subject: [PATCH] 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 --- src/compiler/glsl/lower_vector_derefs.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/compiler/glsl/lower_vector_derefs.cpp b/src/compiler/glsl/lower_vector_derefs.cpp index 2aae30d8201..0c09630fa03 100644 --- a/src/compiler/glsl/lower_vector_derefs.cpp +++ b/src/compiler/glsl/lower_vector_derefs.cpp @@ -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, -- 2.30.2