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 <patrick9876@free.fr>
(cherry picked from commit 0deac18581)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41269>
This commit is contained in:
Patrick Lerda 2026-04-07 13:07:12 +02:00 committed by Eric Engestrom
parent af76112ed9
commit ead15a5202
3 changed files with 46 additions and 2 deletions

View file

@ -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

View file

@ -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)
{

View file

@ -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;