[Mesa-dev] [PATCH] glsl: split ssbo array copies into element copies

Jordan Justen jordan.l.justen at intel.com
Fri Nov 20 11:09:28 PST 2015


On 2015-11-20 06:48:27, Iago Toral Quiroga wrote:
> Improves register pressure, since otherwise we end up emitting
> loads for all the elements in the RHS and them emitting
> stores for all elements in the LHS.
> 
> Fixes the following piglit test:
> tests/spec/arb_shader_storage_buffer_object/execution/large-field-copy.shader_test
> ---
> 
> Jordan, this fixes the link failure for the the test you provided. Needs more
> testing and I have to check if I need to do something for structs that contain
> arrays too, etc I'll do that on Monday unless someone else comes with a better
> idea to fix this.
> 
>  src/glsl/lower_ubo_reference.cpp | 61 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> diff --git a/src/glsl/lower_ubo_reference.cpp b/src/glsl/lower_ubo_reference.cpp
> index b74aa3d..7d48960 100644
> --- a/src/glsl/lower_ubo_reference.cpp
> +++ b/src/glsl/lower_ubo_reference.cpp
> @@ -154,6 +154,7 @@ public:
>     ir_call *ssbo_load(const struct glsl_type *type,
>                        ir_rvalue *offset);
>  
> +   bool check_for_ssbo_array_copy(ir_assignment *ir);
>     void check_for_ssbo_store(ir_assignment *ir);
>     void write_to_memory(ir_dereference *deref,
>                          ir_variable *var,
> @@ -1133,9 +1134,69 @@ lower_ubo_reference_visitor::check_for_ssbo_store(ir_assignment *ir)
>  }
>  
>  
> +bool
> +lower_ubo_reference_visitor::check_for_ssbo_array_copy(ir_assignment *ir)
> +{
> +   if (!ir || !ir->lhs || !ir->rhs)
> +      return false;
> +
> +   ir_dereference *rhs_deref = ir->rhs->as_dereference();
> +   if (!rhs_deref)
> +      return false;
> +
> +   ir_dereference *lhs_deref = ir->lhs->as_dereference();
> +   if (!lhs_deref)
> +      return false;
> +
> +   /* LHS and RHS must be SSBO variables */

Must they? In fact, the issue that prompted this was a copy from an
SSBO to a CS shared variable in the ES3.1 CTS. Maybe just the source
or dest being an SSBO is good enough?

Also, I just re-sent a piglit patch. In this case I just focused on
testing that the shader linked. I tried the 'array' version with this
patch, and it hit an assertion in nir_validate.

The copy 'struct' version still fails to register allocate.

-Jordan

> +   ir_variable *lhs_var = ir->lhs->variable_referenced();
> +   if (!lhs_var || !lhs_var->is_in_shader_storage_block())
> +      return false;
> +
> +   ir_variable *rhs_var = ir->rhs->variable_referenced();
> +   if (!rhs_var || !rhs_var->is_in_shader_storage_block())
> +      return false;
> +
> +   /* LHS and RHS must be variable dereferences.
> +    * FIXME: arrays of arrays?
> +    */
> +   if (!ir->lhs->as_dereference_variable() ||
> +       !ir->rhs->as_dereference_variable())
> +      return false;
> +
> +   /* LHS and RHS must be arrays */
> +   if (!rhs_var->type->is_array() || !lhs_var->type->is_array())
> +      return false;
> +
> +   assert(lhs_deref->type->length == rhs_deref->type->length);
> +
> +   for (unsigned i = 0; i < lhs_deref->type->length; i++) {
> +      ir_dereference *lhs_i =
> +         new(mem_ctx) ir_dereference_array(lhs_deref->clone(mem_ctx, NULL),
> +                                           new(mem_ctx) ir_constant(i));
> +
> +      ir_dereference *rhs_i =
> +         new(mem_ctx) ir_dereference_array(rhs_deref->clone(mem_ctx, NULL),
> +                                           new(mem_ctx) ir_constant(i));
> +      ir->insert_after(assign(lhs_i, rhs_i));
> +   }
> +
> +   ir->remove();
> +   return true;
> +}
> +
>  ir_visitor_status
>  lower_ubo_reference_visitor::visit_enter(ir_assignment *ir)
>  {
> +   /* Array copies could involve large amounts of SSBO load/store
> +    * operations. To improve register pressure we want to special-case
> +    * this and split the array copy into many individual element copies.
> +    * This way we avoid emitting all the loads for the RHS first and
> +    * all the writes for the LHS second.
> +    */
> +   if (check_for_ssbo_array_copy(ir))
> +      return visit_continue_with_parent;
> +
>     check_ssbo_unsized_array_length_assignment(ir);
>     check_for_ssbo_store(ir);
>     return rvalue_visit(ir);
> -- 
> 1.9.1
> 


More information about the mesa-dev mailing list