summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/glsl/lower_vector_derefs.cpp21
1 files changed, 21 insertions, 0 deletions
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,