From: Iago Toral Quiroga Date: Mon, 1 Jun 2015 07:41:47 +0000 (+0200) Subject: i965/nir/fs: Implement nir_intrinsic_ssbo_atomic_* X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=14af6f4698a9f60c080b9adda4d3b4c45b157bd7;p=mesa.git i965/nir/fs: Implement nir_intrinsic_ssbo_atomic_* Reviewed-by: Kristian Høgsberg --- diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 58205084549..50ce4155f16 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -256,6 +256,8 @@ public: nir_ssa_undef_instr *instr); void nir_emit_intrinsic(const brw::fs_builder &bld, nir_intrinsic_instr *instr); + void nir_emit_ssbo_atomic(const brw::fs_builder &bld, + int op, nir_intrinsic_instr *instr); void nir_emit_texture(const brw::fs_builder &bld, nir_tex_instr *instr); void nir_emit_jump(const brw::fs_builder &bld, diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index a05698e53e2..a2bc5c64e4e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -1867,6 +1867,37 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr break; } + case nir_intrinsic_ssbo_atomic_add: + nir_emit_ssbo_atomic(bld, BRW_AOP_ADD, instr); + break; + case nir_intrinsic_ssbo_atomic_min: + if (dest.type == BRW_REGISTER_TYPE_D) + nir_emit_ssbo_atomic(bld, BRW_AOP_IMIN, instr); + else + nir_emit_ssbo_atomic(bld, BRW_AOP_UMIN, instr); + break; + case nir_intrinsic_ssbo_atomic_max: + if (dest.type == BRW_REGISTER_TYPE_D) + nir_emit_ssbo_atomic(bld, BRW_AOP_IMAX, instr); + else + nir_emit_ssbo_atomic(bld, BRW_AOP_UMAX, instr); + break; + case nir_intrinsic_ssbo_atomic_and: + nir_emit_ssbo_atomic(bld, BRW_AOP_AND, instr); + break; + case nir_intrinsic_ssbo_atomic_or: + nir_emit_ssbo_atomic(bld, BRW_AOP_OR, instr); + break; + case nir_intrinsic_ssbo_atomic_xor: + nir_emit_ssbo_atomic(bld, BRW_AOP_XOR, instr); + break; + case nir_intrinsic_ssbo_atomic_exchange: + nir_emit_ssbo_atomic(bld, BRW_AOP_MOV, instr); + break; + case nir_intrinsic_ssbo_atomic_comp_swap: + nir_emit_ssbo_atomic(bld, BRW_AOP_CMPWR, instr); + break; + case nir_intrinsic_get_buffer_size: { nir_const_value *const_uniform_block = nir_src_as_const_value(instr->src[0]); unsigned ubo_index = const_uniform_block ? const_uniform_block->u[0] : 0; @@ -1896,6 +1927,52 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr } } +void +fs_visitor::nir_emit_ssbo_atomic(const fs_builder &bld, + int op, nir_intrinsic_instr *instr) +{ + fs_reg dest; + if (nir_intrinsic_infos[instr->intrinsic].has_dest) + dest = get_nir_dest(instr->dest); + + fs_reg surface; + nir_const_value *const_surface = nir_src_as_const_value(instr->src[0]); + if (const_surface) { + unsigned surf_index = stage_prog_data->binding_table.ubo_start + + const_surface->u[0]; + surface = fs_reg(surf_index); + brw_mark_surface_used(prog_data, surf_index); + } else { + surface = vgrf(glsl_type::uint_type); + bld.ADD(surface, get_nir_src(instr->src[0]), + fs_reg(stage_prog_data->binding_table.ubo_start)); + + /* Assume this may touch any UBO. This is the same we do for other + * UBO/SSBO accesses with non-constant surface. + */ + brw_mark_surface_used(prog_data, + stage_prog_data->binding_table.ubo_start + + shader_prog->NumUniformBlocks - 1); + } + + fs_reg offset = get_nir_src(instr->src[1]); + fs_reg data1 = get_nir_src(instr->src[2]); + fs_reg data2; + if (op == BRW_AOP_CMPWR) + data2 = get_nir_src(instr->src[3]); + + /* Emit the actual atomic operation operation */ + + fs_reg atomic_result = + surface_access::emit_untyped_atomic(bld, surface, offset, + data1, data2, + 1 /* dims */, 1 /* rsize */, + op, + BRW_PREDICATE_NONE); + dest.type = atomic_result.type; + bld.MOV(dest, atomic_result); +} + void fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr) {