glsl: Don't lower vector derefs for SSBOs, UBOs, and shared
authorJason Ekstrand <jason.ekstrand@intel.com>
Mon, 11 Mar 2019 19:53:31 +0000 (14:53 -0500)
committerJason Ekstrand <jason@jlekstrand.net>
Fri, 15 Mar 2019 01:02:19 +0000 (01:02 +0000)
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>
src/compiler/glsl/lower_vector_derefs.cpp

index 2aae30d8201101d2c4afcf6ce4a632aad3eda02a..0c09630fa0301b3f9f8949a37b92a91bf35767d3 100644 (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,