--- src/mesa/drivers/dri/i965/brw_fs.h | 1 + src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index a02912f..b87fef0 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -316,6 +316,7 @@ public: void nir_emit_instr(nir_instr *instr); void nir_emit_alu(nir_alu_instr *instr); void nir_emit_intrinsic(nir_intrinsic_instr *instr); + void nir_emit_ssbo_atomic(int op, nir_intrinsic_instr *instr); void nir_emit_texture(nir_tex_instr *instr); void nir_emit_jump(nir_jump_instr *instr); fs_reg get_nir_src(nir_src src); diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 15c1500..36b670b 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -1719,6 +1719,37 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) break; } + case nir_intrinsic_ssbo_atomic_add: + nir_emit_ssbo_atomic(BRW_AOP_ADD, instr); + break; + case nir_intrinsic_ssbo_atomic_min: + if (dest.type == BRW_REGISTER_TYPE_D) + nir_emit_ssbo_atomic(BRW_AOP_IMIN, instr); + else + nir_emit_ssbo_atomic(BRW_AOP_UMIN, instr); + break; + case nir_intrinsic_ssbo_atomic_max: + if (dest.type == BRW_REGISTER_TYPE_D) + nir_emit_ssbo_atomic(BRW_AOP_IMAX, instr); + else + nir_emit_ssbo_atomic(BRW_AOP_UMAX, instr); + break; + case nir_intrinsic_ssbo_atomic_and: + nir_emit_ssbo_atomic(BRW_AOP_AND, instr); + break; + case nir_intrinsic_ssbo_atomic_or: + nir_emit_ssbo_atomic(BRW_AOP_OR, instr); + break; + case nir_intrinsic_ssbo_atomic_xor: + nir_emit_ssbo_atomic(BRW_AOP_XOR, instr); + break; + case nir_intrinsic_ssbo_atomic_exchange: + nir_emit_ssbo_atomic(BRW_AOP_MOV, instr); + break; + case nir_intrinsic_ssbo_atomic_comp_swap: + nir_emit_ssbo_atomic(BRW_AOP_CMPWR, instr); + break; + case nir_intrinsic_ssbo_unsized_array_length: { 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; @@ -1776,6 +1807,57 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) } void +fs_visitor::nir_emit_ssbo_atomic(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); + emit(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 */ + const bool uses_kill = (stage == MESA_SHADER_FRAGMENT && + ((brw_wm_prog_data *)prog_data)->uses_kill); + fs_builder bld(devinfo, mem_ctx, alloc, instructions, dispatch_width, + stage, uses_kill); + bld.set_annotation(current_annotation); + bld.set_base_ir(base_ir); + + 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; + emit(MOV(dest, atomic_result)); +} + +void fs_visitor::nir_emit_texture(nir_tex_instr *instr) { unsigned sampler = instr->sampler_index; -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev