From ead15a520271f557c3636e2653686e3404bfabe6 Mon Sep 17 00:00:00 2001 From: Patrick Lerda Date: Tue, 7 Apr 2026 13:07:12 +0200 Subject: [PATCH] r600: fix atomic_counter_post_dec This change was tested on plam and cayman. Here are the tests fixed: spec/arb_gl_spirv/execution/uniform/atomic-uint-aoa-cs: fail pass spec/arb_gl_spirv/execution/uniform/atomic-uint-aoa-fs: fail pass spec/arb_gl_spirv/execution/uniform/atomic-uint-array-cs: fail pass spec/arb_gl_spirv/execution/uniform/atomic-uint-array-fs: fail pass spec/arb_gl_spirv/execution/uniform/atomic-uint-cs: fail pass spec/arb_gl_spirv/execution/uniform/atomic-uint-fs: fail pass Cc: mesa-stable Signed-off-by: Patrick Lerda (cherry picked from commit 0deac18581e80926b5cedf49848b74e90bb57db3) Part-of: --- .pick_status.json | 2 +- .../drivers/r600/sfn/sfn_instr_mem.cpp | 45 ++++++++++++++++++- src/gallium/drivers/r600/sfn/sfn_instr_mem.h | 1 + 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 12663d1569f..f1ef6c8d7bf 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -4274,7 +4274,7 @@ "description": "r600: fix atomic_counter_post_dec", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp b/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp index 3a0e24712ad..4cf3cc35480 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instr_mem.cpp @@ -91,12 +91,13 @@ GDSInstr::emit_atomic_counter(nir_intrinsic_instr *intr, Shader& shader) case nir_intrinsic_atomic_counter_comp_swap: return emit_atomic_counter_comp_swap(intr, shader); case nir_intrinsic_atomic_counter_read: - case nir_intrinsic_atomic_counter_post_dec: return emit_atomic_read(intr, shader); case nir_intrinsic_atomic_counter_inc: return emit_atomic_inc(intr, shader); case nir_intrinsic_atomic_counter_pre_dec: return emit_atomic_pre_dec(intr, shader); + case nir_intrinsic_atomic_counter_post_dec: + return emit_atomic_post_dec(intr, shader); default: return false; } @@ -353,6 +354,48 @@ GDSInstr::emit_atomic_pre_dec(nir_intrinsic_instr *instr, Shader& shader) return true; } +bool +GDSInstr::emit_atomic_post_dec(nir_intrinsic_instr *instr, Shader& shader) +{ + auto& vf = shader.value_factory(); + + bool read_result = !list_is_empty(&instr->def.uses); + + auto opcode = read_result ? DS_OP_SUB_RET : DS_OP_SUB; + + auto [offset, uav_id] = shader.evaluate_resource_offset(instr, 0); + + offset += shader.remap_atomic_base(nir_intrinsic_base(instr)); + + auto *dest = read_result ? vf.dest(instr->def, 0, pin_free) : nullptr; + + GDSInstr *ir = nullptr; + + if (shader.chip_class() < ISA_CC_CAYMAN) { + RegisterVec4 src(nullptr, shader.atomic_update(), nullptr, nullptr, pin_chan); + ir = new GDSInstr(opcode, dest, src, offset, uav_id); + } else { + auto tmp = vf.temp_vec4(pin_group, {0, 1, 7, 7}); + if (uav_id) + shader.emit_instruction(new AluInstr(op3_muladd_uint24, + tmp[0], + uav_id, + vf.literal(4), + vf.literal(4 * offset), + AluInstr::write)); + else + shader.emit_instruction( + new AluInstr(op1_mov, tmp[0], vf.literal(4 * offset), AluInstr::write)); + + shader.emit_instruction( + new AluInstr(op1_mov, tmp[1], shader.atomic_update(), AluInstr::write)); + ir = new GDSInstr(opcode, dest, tmp, 0, nullptr); + } + + shader.emit_instruction(ir); + return true; +} + bool GDSInstr::emit_atomic_counter_comp_swap(nir_intrinsic_instr *instr, Shader& shader) { diff --git a/src/gallium/drivers/r600/sfn/sfn_instr_mem.h b/src/gallium/drivers/r600/sfn/sfn_instr_mem.h index 81f2df71a99..2b7cabf4b24 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instr_mem.h +++ b/src/gallium/drivers/r600/sfn/sfn_instr_mem.h @@ -46,6 +46,7 @@ private: static bool emit_atomic_op2(nir_intrinsic_instr *intr, Shader& shader); static bool emit_atomic_inc(nir_intrinsic_instr *intr, Shader& shader); static bool emit_atomic_pre_dec(nir_intrinsic_instr *intr, Shader& shader); + static bool emit_atomic_post_dec(nir_intrinsic_instr *intr, Shader& shader); static bool emit_atomic_counter_comp_swap(nir_intrinsic_instr *intr, Shader& shader); void do_print(std::ostream& os) const override;