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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev