[Mesa-dev] [PATCH v3 (part2) 29/56] i965/vec4: Implement SSBO reads

Iago Toral Quiroga itoral at igalia.com
Tue Jul 14 00:46:31 PDT 2015


---
 src/mesa/drivers/dri/i965/brw_vec4.h           |  1 +
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 76 ++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 870946b..d5f5ef9 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -384,6 +384,7 @@ public:
    void visit_atomic_counter_intrinsic(ir_call *ir);
 
    void visit_store_ssbo_intrinsic(ir_call *ir);
+   void visit_load_ssbo_intrinsic(ir_call *ir);
 
 protected:
    void emit_vertex();
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index dbdfdd3..a5591e6 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2649,6 +2649,80 @@ vec4_visitor::visit_store_ssbo_intrinsic(ir_call *ir)
 }
 
 void
+vec4_visitor::visit_load_ssbo_intrinsic(ir_call *ir)
+{
+   const glsl_type *type = ir->return_deref->var->type;
+   assert(type->is_vector() || type->is_scalar());
+
+   /* Block */
+   exec_node *param = ir->actual_parameters.get_head();
+   ir_rvalue *block_param = ((ir_instruction *)param)->as_rvalue();
+   ir_constant *const_uniform_block = block_param->as_constant();
+   src_reg surf_index;
+
+   /* Storage for our result.  Ideally for an assignment we'd be using
+    * the actual storage for the result here, instead.
+    */
+   dst_reg result_dst = get_assignment_lhs(ir->return_deref, this);
+   src_reg result_src(result_dst);
+   this->result = result_src;
+
+   if (const_uniform_block) {
+      /* The block index is a constant, so just emit the binding table entry
+       * as an immediate.
+       */
+      unsigned index = prog_data->base.binding_table.ubo_start +
+                       const_uniform_block->value.u[0];
+      surf_index = src_reg(index);
+
+      brw_mark_surface_used(&prog_data->base, index);
+   } else {
+      /* The block index is not a constant. Evaluate the index expression
+       * per-channel and add the base UBO index; we have to select a value
+       * from any live channel.
+       */
+      block_param->accept(this);
+      src_reg block_reg = this->result;
+
+      surf_index = src_reg(this, glsl_type::uint_type);
+      emit(ADD(dst_reg(surf_index), block_reg,
+               src_reg(prog_data->base.binding_table.ubo_start)));
+      emit_uniformize(dst_reg(surf_index), surf_index);
+
+      /* Assume this may touch any UBO. It would be nice to provide
+       * a tighter bound, but the array information is already lowered away.
+       */
+      brw_mark_surface_used(&prog_data->base,
+                            prog_data->base.binding_table.ubo_start +
+                            shader_prog->NumUniformBlocks - 1);
+   }
+
+   /* Offset */
+   param = param->get_next();
+   ir_rvalue *offset_param = ((ir_instruction *)param)->as_rvalue();
+   offset_param->accept(this);
+   src_reg offset = src_reg(this, glsl_type::uint_type);
+   emit(MOV(dst_reg(offset), this->result));
+
+   /* Read the vector */
+   const vec4_builder bld = vec4_builder(this).at_end()
+      .annotate(current_annotation, base_ir);
+
+   src_reg read_result = emit_untyped_read(bld, surf_index, offset,
+                                           1 /* dims */, 4 /* size*/,
+                                           BRW_PREDICATE_NONE);
+   read_result.type = result_dst.type;
+   read_result.swizzle = brw_swizzle_for_size(type->vector_elements);
+
+   /* SSBO/UBO bools are any nonzero int.  We need to convert them to 0/~0. */
+   if (type->base_type == GLSL_TYPE_BOOL) {
+      emit(CMP(result_dst, read_result, src_reg(0u), BRW_CONDITIONAL_NZ));
+   } else {
+      emit(MOV(result_dst, read_result));
+   }
+}
+
+void
 vec4_visitor::visit(ir_call *ir)
 {
    const char *callee = ir->callee->function_name();
@@ -2659,6 +2733,8 @@ vec4_visitor::visit(ir_call *ir)
       visit_atomic_counter_intrinsic(ir);
    } else if (!strcmp("__intrinsic_store_ssbo", callee)) {
       visit_store_ssbo_intrinsic(ir);
+   } else if (!strcmp("__intrinsic_load_ssbo", callee)) {
+      visit_load_ssbo_intrinsic(ir);
    } else {
       unreachable("Unsupported intrinsic.");
    }
-- 
1.9.1



More information about the mesa-dev mailing list