[Mesa-dev] [PATCH 25/29] i965/fs: Import GLSL IR image intrinsic translation code.

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


v2: Drop VEC4 suport.
---
 src/mesa/drivers/dri/i965/brw_fs.h           |   1 +
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 142 +++++++++++++++++++++++++++
 2 files changed, 143 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 6d3701c..e4f3c25 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -447,6 +447,7 @@ public:
    void dump_instruction(backend_instruction *inst, FILE *file);
 
    void visit_atomic_counter_intrinsic(const brw::fs_builder &bld, ir_call *ir);
+   void visit_image_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 57076c5..f3e7ad1 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -44,6 +44,7 @@
 #include "brw_fs.h"
 #include "brw_fs_surface_builder.h"
 #include "main/uniforms.h"
+#include "main/shaderimage.h"
 #include "glsl/glsl_types.h"
 #include "glsl/ir_optimization.h"
 #include "program/sampler.h"
@@ -3216,6 +3217,134 @@ fs_visitor::visit_atomic_counter_intrinsic(const fs_builder &bld, ir_call *ir)
       bld.MOV(visit_result(ir->return_deref), tmp);
 }
 
+/**
+ * Get the appropriate atomic op for an image atomic intrinsic.
+ */
+static unsigned
+get_image_atomic_op(const char *callee, const glsl_type *type)
+{
+   const glsl_base_type base_type = (glsl_base_type)type->sampler_type;
+
+   if (!strcmp("__intrinsic_image_atomic_add", callee))
+      return BRW_AOP_ADD;
+
+   else if (!strcmp("__intrinsic_image_atomic_min", callee))
+      return (base_type == GLSL_TYPE_UINT ? BRW_AOP_UMIN : BRW_AOP_IMIN);
+
+   else if (!strcmp("__intrinsic_image_atomic_max", callee))
+      return (base_type == GLSL_TYPE_UINT ? BRW_AOP_UMAX : BRW_AOP_IMAX);
+
+   else if (!strcmp("__intrinsic_image_atomic_and", callee))
+      return BRW_AOP_AND;
+
+   else if (!strcmp("__intrinsic_image_atomic_or", callee))
+      return BRW_AOP_OR;
+
+   else if (!strcmp("__intrinsic_image_atomic_xor", callee))
+      return BRW_AOP_XOR;
+
+   else if (!strcmp("__intrinsic_image_atomic_exchange", callee))
+      return BRW_AOP_MOV;
+
+   else if (!strcmp("__intrinsic_image_atomic_comp_swap", callee))
+      return BRW_AOP_CMPWR;
+
+   else
+      unreachable("Not reachable.");
+}
+
+/**
+ * Return true if the image is a 1D array and the implementation
+ * requires the array index to be passed in as the Z component of the
+ * coordinate vector.
+ */
+static bool
+needs_zero_y_image_coordinate(const fs_builder &bld,
+                              const ir_variable *image)
+{
+   const glsl_type *type = image->type->without_array();
+   const mesa_format format =
+      _mesa_get_shader_image_format(image->data.image_format);
+   /* HSW in vec4 mode and our software coordinate handling for untyped
+    * reads want the array index to be at the Z component.
+    */
+   const bool array_index_at_z = !image->data.image_write_only &&
+      !image_format_info::has_matching_typed_format(bld.devinfo, format);
+
+   return (type->sampler_dimensionality == GLSL_SAMPLER_DIM_1D &&
+           type->sampler_array && array_index_at_z);
+}
+
+/**
+ * Transform image coordinates into the form expected by the
+ * implementation.
+ */
+static fs_reg
+fix_image_address(const fs_builder &bld,
+                  const ir_variable *image, const fs_reg &addr)
+{
+   if (needs_zero_y_image_coordinate(bld, image)) {
+      assert(image->type->without_array()->coordinate_components() == 2);
+      const fs_reg tmp = bld.vgrf(addr.type, 3);
+
+      bld.MOV(tmp, addr);
+      bld.MOV(offset(tmp, 1), fs_reg(0));
+      bld.MOV(offset(tmp, 2), offset(addr, 1));
+
+      return tmp;
+   } else {
+      return addr;
+   }
+}
+
+void
+fs_visitor::visit_image_intrinsic(const fs_builder &bld, ir_call *ir)
+{
+   using namespace image_access;
+
+   /* Get the referenced image variable and type. */
+   const ir_variable *var = static_cast<ir_dereference *>(
+      ir->actual_parameters.get_head())->variable_referenced();
+   const glsl_type *type = var->type->without_array();
+
+   /* Visit the arguments of the image intrinsic. */
+   const unsigned first_src_idx =
+      (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS ? 3 : 2);
+   const fs_reg image = visit_argument(this, ir, 0);
+   const fs_reg addr = fix_image_address(bld, var,
+                                         visit_argument(this, ir, 1));
+   const fs_reg src0 = visit_argument(this, ir, first_src_idx);
+   const fs_reg src1 = visit_argument(this, ir, first_src_idx + 1);
+
+   /* Get some metadata from the image intrinsic. */
+   const char *callee = ir->callee->function_name();
+   const unsigned dims = (type->coordinate_components() +
+                          (needs_zero_y_image_coordinate(bld, var) ? 1 : 0));
+   const mesa_format format =
+      (var->data.image_write_only ? MESA_FORMAT_NONE :
+       _mesa_get_shader_image_format(var->data.image_format));
+   fs_reg tmp;
+
+   /* Emit an image load, store or atomic op. */
+   if (!strcmp("__intrinsic_image_load", callee))
+      tmp = emit_image_load(bld, image, addr, format, dims);
+
+   else if (!strcmp("__intrinsic_image_store", callee))
+      emit_image_store(bld, image, addr, src0, format, dims);
+
+   else
+      tmp = emit_image_atomic(bld, image, addr, src0, src1,
+                              dims, (ir->return_deref ? 1 : 0),
+                              get_image_atomic_op(callee, type));
+
+   /* Assign the result. */
+   if (ir->return_deref) {
+      const fs_reg dst = visit_result(ir->return_deref);
+      for (unsigned c = 0; c < ir->return_deref->type->vector_elements; ++c)
+         bld.MOV(offset(dst, c), offset(tmp, c));
+   }
+}
+
 void
 fs_visitor::visit(ir_call *ir)
 {
@@ -3232,6 +3361,19 @@ fs_visitor::visit(ir_call *ir)
        !strcmp("__intrinsic_atomic_increment", callee) ||
        !strcmp("__intrinsic_atomic_predecrement", callee)) {
       visit_atomic_counter_intrinsic(bld, ir);
+
+   } else if (!strcmp("__intrinsic_image_load", callee) ||
+              !strcmp("__intrinsic_image_store", callee) ||
+              !strcmp("__intrinsic_image_atomic_add", callee) ||
+              !strcmp("__intrinsic_image_atomic_min", callee) ||
+              !strcmp("__intrinsic_image_atomic_max", callee) ||
+              !strcmp("__intrinsic_image_atomic_and", callee) ||
+              !strcmp("__intrinsic_image_atomic_or", callee) ||
+              !strcmp("__intrinsic_image_atomic_xor", callee) ||
+              !strcmp("__intrinsic_image_atomic_exchange", callee) ||
+              !strcmp("__intrinsic_image_atomic_comp_swap", callee)) {
+      visit_image_intrinsic(bld, ir);
+
    } else {
       unreachable("Unsupported intrinsic.");
    }
-- 
2.3.5



More information about the mesa-dev mailing list