This can deal with all the 15 32-bit untyped atomic operations the hardware supports, but only INC and PREDEC are going to be exposed through the API for now. --- src/mesa/drivers/dri/i965/brw_fs.h | 7 +++ src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 83 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index dcd489c..44930f7 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -392,6 +392,13 @@ public: void emit_shader_time_write(enum shader_time_shader_type type, fs_reg value); + void emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, + unsigned offset, fs_reg dst, fs_reg src0, + fs_reg src1); + + void emit_untyped_surface_read(unsigned surf_index, unsigned offset, + fs_reg dst); + bool try_rewrite_rhs_to_dst(ir_assignment *ir, fs_reg dst, fs_reg src, diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 762832a..412d27a 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -2112,8 +2112,91 @@ fs_visitor::visit(ir_end_primitive *) } void +fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, + unsigned offset, fs_reg dst, fs_reg src0, + fs_reg src1) +{ + const unsigned operand_len = dispatch_width / 8; + unsigned mlen = 0; + + /* Initialize the sample mask in the message header. */ + emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0))) + ->force_writemask_all = true; + emit(MOV(brw_uvec_mrf(1, mlen, 7), + retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD))) + ->force_writemask_all = true; + mlen++; + + /* Set the atomic operation offset. */ + emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), brw_imm_ud(offset))); + mlen += operand_len; + + /* Set the atomic operation arguments. */ + if (src0.file != BAD_FILE) { + emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src0)); + mlen += operand_len; + } + + if (src1.file != BAD_FILE) { + emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), src1)); + mlen += operand_len; + } + + /* Emit the instruction. */ + fs_inst inst(SHADER_OPCODE_UNTYPED_ATOMIC, dst, + fs_reg(atomic_op), fs_reg(surf_index)); + inst.base_mrf = 0; + inst.mlen = mlen; + emit(inst); +} + +void +fs_visitor::emit_untyped_surface_read(unsigned surf_index, unsigned offset, + fs_reg dst) +{ + const unsigned operand_len = dispatch_width / 8; + unsigned mlen = 0; + + /* Initialize the sample mask in the message header. */ + emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0))) + ->force_writemask_all = true; + emit(MOV(brw_uvec_mrf(1, mlen, 7), + retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UD))) + ->force_writemask_all = true; + mlen++; + + /* Set the surface read offset. */ + emit(MOV(brw_uvec_mrf(dispatch_width, mlen, 0), brw_imm_ud(offset))); + mlen += operand_len; + + /* Emit the instruction. */ + fs_inst inst(SHADER_OPCODE_UNTYPED_SURFACE_READ, dst, fs_reg(surf_index)); + inst.base_mrf = 0; + inst.mlen = mlen; + emit(inst); +} + +void fs_visitor::visit(ir_atomic *ir) { + ir_variable *loc = ir->location->variable_referenced(); + unsigned surf_index = SURF_INDEX_WM_ABO(loc->atomic.buffer_index); + + result = fs_reg(this, ir->type); + + switch (ir->op) { + case ir_atomic_read: + emit_untyped_surface_read(surf_index, loc->atomic.offset, result); + break; + case ir_atomic_inc: + emit_untyped_atomic(BRW_AOP_INC, surf_index, loc->atomic.offset, + result, fs_reg(), fs_reg()); + break; + case ir_atomic_dec: + emit_untyped_atomic(BRW_AOP_PREDEC, surf_index, loc->atomic.offset, + result, fs_reg(), fs_reg()); + break; + } } fs_inst * -- 1.8.3.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev