[Mesa-dev] [PATCH 23/29] i965/fs: Revisit GLSL IR atomic counter intrinsic translation.

Francisco Jerez currojerez at riseup.net
Sat May 2 08:29:50 PDT 2015


This is a rewrite of the GLSL IR atomic counter intrinsics translation
code based on the recently introduced surface builder.

v2: Drop VEC4 suport.
---
 src/mesa/drivers/dri/i965/brw_fs.h           |  3 +-
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 79 ++++++++++++++++++++--------
 2 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 0834ca5..6d3701c 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -59,6 +59,7 @@ namespace {
 
 namespace brw {
    class fs_live_variables;
+   class fs_builder;
 }
 
 /**
@@ -445,7 +446,7 @@ public:
    void dump_instruction(backend_instruction *inst);
    void dump_instruction(backend_instruction *inst, FILE *file);
 
-   void visit_atomic_counter_intrinsic(ir_call *ir);
+   void visit_atomic_counter_intrinsic(const brw::fs_builder &bld, ir_call *ir);
 
    const void *const key;
    const struct brw_sampler_prog_key_data *key_tex;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 9c394ba..57076c5 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -42,11 +42,13 @@
 #include "brw_cs.h"
 #include "brw_vec4.h"
 #include "brw_fs.h"
+#include "brw_fs_surface_builder.h"
 #include "main/uniforms.h"
 #include "glsl/glsl_types.h"
 #include "glsl/ir_optimization.h"
 #include "program/sampler.h"
 
+using namespace brw;
 
 fs_reg *
 fs_visitor::emit_vs_system_value(int location)
@@ -3160,43 +3162,76 @@ fs_visitor::visit(ir_loop_jump *ir)
    }
 }
 
+/**
+ * Process the i-th parameter passed to an intrinsic call.
+ */
+static fs_reg
+visit_argument(fs_visitor *v, ir_call *ir, unsigned i)
+{
+   unsigned j = 0;
+
+   foreach_in_list(ir_dereference, arg, &ir->actual_parameters) {
+      if (j++ == i)
+         return v->visit_result(arg);
+   }
+
+   return fs_reg();
+}
+
 void
-fs_visitor::visit_atomic_counter_intrinsic(ir_call *ir)
+fs_visitor::visit_atomic_counter_intrinsic(const fs_builder &bld, ir_call *ir)
 {
-   ir_dereference *deref = static_cast<ir_dereference *>(
-      ir->actual_parameters.get_head());
-   ir_variable *location = deref->variable_referenced();
-   unsigned surf_index = (stage_prog_data->binding_table.abo_start +
-                          location->data.binding);
-   const fs_reg offset = visit_result(deref);
-
-   /* Emit the appropriate machine instruction */
-   const char *callee = ir->callee->function_name();
-   ir->return_deref->accept(this);
-   fs_reg dst = this->result;
+   using namespace surface_access;
 
-   if (!strcmp("__intrinsic_atomic_read", callee)) {
-      emit_untyped_surface_read(surf_index, dst, offset);
+   /* Get the referenced atomic counter variable. */
+   const ir_variable *var = static_cast<ir_dereference *>(
+      ir->actual_parameters.get_head())->variable_referenced();
 
-   } else if (!strcmp("__intrinsic_atomic_increment", callee)) {
-      emit_untyped_atomic(BRW_AOP_INC, surf_index, dst, offset,
-                          fs_reg(), fs_reg());
+   /* Visit the arguments of the atomic intrinsic. */
+   const fs_reg offset = visit_argument(this, ir, 0);
+   const fs_reg surface(stage_prog_data->binding_table.abo_start +
+                        var->data.binding);
 
-   } else if (!strcmp("__intrinsic_atomic_predecrement", callee)) {
-      emit_untyped_atomic(BRW_AOP_PREDEC, surf_index, dst, offset,
-                          fs_reg(), fs_reg());
-   }
+   /* Get some metadata from the atomic intrinsic. */
+   const char *callee = ir->callee->function_name();
+   const unsigned rsize = (ir->return_deref ? 1 : 0);
+   fs_reg tmp;
+
+   /* Emit a surface read or atomic op. */
+   if (!strcmp("__intrinsic_atomic_read", callee))
+      tmp = surface_access::emit_untyped_read(bld, surface, offset, 1, 1);
+
+   else if (!strcmp("__intrinsic_atomic_increment", callee))
+      tmp = surface_access::emit_untyped_atomic(
+         bld, surface, offset, fs_reg(), fs_reg(),
+         1, rsize, BRW_AOP_INC);
+
+   else if (!strcmp("__intrinsic_atomic_predecrement", callee))
+      tmp = surface_access::emit_untyped_atomic(
+         bld, surface, offset, fs_reg(), fs_reg(),
+         1, rsize, BRW_AOP_PREDEC);
+
+   /* Assign the result. */
+   if (ir->return_deref)
+      bld.MOV(visit_result(ir->return_deref), tmp);
 }
 
 void
 fs_visitor::visit(ir_call *ir)
 {
    const char *callee = ir->callee->function_name();
+   const bool uses_kill = (stage == MESA_SHADER_FRAGMENT &&
+                           ((brw_wm_prog_data *)prog_data)->uses_kill);
+   fs_builder bld(devinfo, mem_ctx, alloc, instructions, dispatch_width,
+                  stage, uses_kill);
+
+   bld.set_annotation(current_annotation);
+   bld.set_base_ir(base_ir);
 
    if (!strcmp("__intrinsic_atomic_read", callee) ||
        !strcmp("__intrinsic_atomic_increment", callee) ||
        !strcmp("__intrinsic_atomic_predecrement", callee)) {
-      visit_atomic_counter_intrinsic(ir);
+      visit_atomic_counter_intrinsic(bld, ir);
    } else {
       unreachable("Unsupported intrinsic.");
    }
-- 
2.3.5



More information about the mesa-dev mailing list