summaryrefslogtreecommitdiffstats
path: root/src/glsl/lower_ubo_reference.cpp
diff options
context:
space:
mode:
authorKristian Høgsberg Kristensen <[email protected]>2015-11-04 14:58:54 -0800
committerKristian Høgsberg Kristensen <[email protected]>2015-11-10 12:02:46 -0800
commit96b22fb080894ba1840af2372f28a46cc0f40c76 (patch)
tree197f2454ecfd1778eeea2d81146682ff35fce01e /src/glsl/lower_ubo_reference.cpp
parent60dd5287ff8dbbbe0dbe76bdff6d13c7a5ea9ef0 (diff)
glsl: Use array deref for access to vector components
We've assumed that we could lower per-component vector access from vec[i] = scalar to vec = ir_triop_vector_insert(vec, scalar, i) but with SSBOs (and compute shader SLM and tesselation outputs) this is no longer valid. If a vector is "externally visible", multiple threads can write independent components simultaneously. With lowering to ir_triop_vector_insert, each thread read the entire vector, changes one component, then writes out the entire vector. This is racy. Instead of generating a ir_binop_vector_extract when we see v[i], we generate ir_dereference_array. We then add a lowering pass to lower the ir_dereference_array to ir_binop_vector_extract for rvalues and for to vector_insert for lvalues in a separate lowering pass. The resulting IR is the same as before, but we now have a window between ast->ir conversion and the lowering pass where v[i] appears in the IR as an array deref. This lets us run lowering passes that lower the vector access to I/O (eg for SSBO load/store) before we lower the per-component access to full vector writes. Reviewed-by: Jordan Justen <[email protected]> Signed-off-by: Kristian Høgsberg Kristensen <[email protected]>
Diffstat (limited to 'src/glsl/lower_ubo_reference.cpp')
-rw-r--r--src/glsl/lower_ubo_reference.cpp14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/glsl/lower_ubo_reference.cpp b/src/glsl/lower_ubo_reference.cpp
index 24806ac6ce9..b74aa3d0630 100644
--- a/src/glsl/lower_ubo_reference.cpp
+++ b/src/glsl/lower_ubo_reference.cpp
@@ -390,7 +390,19 @@ lower_ubo_reference_visitor::setup_for_load_or_store(ir_variable *var,
case ir_type_dereference_array: {
ir_dereference_array *deref_array = (ir_dereference_array *) deref;
unsigned array_stride;
- if (deref_array->array->type->is_matrix() && *row_major) {
+ if (deref_array->array->type->is_vector()) {
+ /* We get this when storing or loading a component out of a vector
+ * with a non-constant index. This happens for v[i] = f where v is
+ * a vector (or m[i][j] = f where m is a matrix). If we don't
+ * lower that here, it gets turned into v = vector_insert(v, i,
+ * f), which loads the entire vector, modifies one component and
+ * then write the entire thing back. That breaks if another
+ * thread or SIMD channel is modifying the same vector.
+ */
+ array_stride = 4;
+ if (deref_array->array->type->is_double())
+ array_stride *= 2;
+ } else if (deref_array->array->type->is_matrix() && *row_major) {
/* When loading a vector out of a row major matrix, the
* step between the columns (vectors) is the size of a
* float, while the step between the rows (elements of a