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,