--- src/mesa/drivers/dri/i965/brw_ir_glsl_intrinsics.h | 136 +++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_reg.h | 1 + 2 files changed, 137 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_ir_glsl_intrinsics.h b/src/mesa/drivers/dri/i965/brw_ir_glsl_intrinsics.h index cc838e9..df7b1a3 100644 --- a/src/mesa/drivers/dri/i965/brw_ir_glsl_intrinsics.h +++ b/src/mesa/drivers/dri/i965/brw_ir_glsl_intrinsics.h @@ -95,6 +95,142 @@ namespace brw { if (ir->return_deref) vbld.MOV(dst_reg(v->visit_result(ir->return_deref)), tmp); } + + namespace detail { + /** + * Get the appropriate atomic op for an image atomic intrinsic. + */ + inline 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. + */ + template<typename B> + inline bool + needs_zero_y_image_coordinate(const B &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 = + (bld.devinfo->is_haswell && B::dst_reg::traits::chan_size == 4) || + (!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. + */ + template<typename B, typename S> + S + fix_image_address(const B &bld, const ir_variable *image, const S &addr) + { + if (needs_zero_y_image_coordinate(bld, image)) { + const typename B::dst_reg tmp = bld.natural_reg(addr.type); + + bld.MOV(writemask(tmp, WRITEMASK_XZW), + swizzle(addr, BRW_SWIZZLE_XWYZ)); + bld.MOV(writemask(tmp, WRITEMASK_Y), 0); + + return tmp; + } else { + return addr; + } + } + } + + /** + * Entry point for translating GLSL IR image intrinsics. + */ + template<typename V, typename B> + void + visit_image_intrinsic(V *v, const B &bld, ir_call *ir) + { + using namespace detail; + using namespace image_access; + typedef typename B::vector_builder::src_reg src_reg; + typename B::vector_builder vbld = bld.vector(); + + /* 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 src_reg image = visit_argument<src_reg>(v, ir, 0); + const src_reg addr = fix_image_address(vbld, var, + visit_argument<src_reg>(v, ir, 1)); + const src_reg src0 = visit_argument<src_reg>(v, ir, first_src_idx); + const src_reg src1 = visit_argument<src_reg>(v, 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)); + src_reg tmp; + + /* Emit an image load, store or atomic op. */ + if (!strcmp("__intrinsic_image_load", callee)) + tmp = emit_image_load(vbld, image, addr, format, dims); + + else if (!strcmp("__intrinsic_image_store", callee)) + emit_image_store(vbld, image, addr, src0, format, dims); + + else + tmp = emit_image_atomic(vbld, image, addr, src0, src1, + dims, (ir->return_deref ? 1 : 0), + get_image_atomic_op(callee, type)); + + /* Assign the result. */ + if (ir->return_deref) + vbld.MOV(dst_vector(v->visit_result(ir->return_deref), + ir->return_deref->type->vector_elements), tmp); + } } #endif diff --git a/src/mesa/drivers/dri/i965/brw_reg.h b/src/mesa/drivers/dri/i965/brw_reg.h index 668f83c..1db2252b 100644 --- a/src/mesa/drivers/dri/i965/brw_reg.h +++ b/src/mesa/drivers/dri/i965/brw_reg.h @@ -82,6 +82,7 @@ struct brw_device_info; #define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2) #define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3) #define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1) +#define BRW_SWIZZLE_XWYZ BRW_SWIZZLE4(0,3,1,2) #define BRW_SWIZZLE_XZXZ BRW_SWIZZLE4(0,2,0,2) #define BRW_SWIZZLE_YZXW BRW_SWIZZLE4(1,2,0,3) #define BRW_SWIZZLE_YZYZ BRW_SWIZZLE4(1,2,1,2) -- 2.3.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev