[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