test(agc-driver): add a split-lane case with per-lane operands to the LDS mixed-width atomic test

On RADV the race between ds_add_u64 under the workgroup lock and a
concurrent ds_add_u32 only shows when the lanes get their operands from
per-lane buffer loads: with v_mov_b32 constants or loads from one address
no increment is lost there. The new case has the split-lane kernel's
parity split and loads each lane's (0xffffffff, 0, 1, 0) row from the input
buffer at tid * 16 with buffer_load_dwordx4, so the input buffer now holds
256 rows. With SpirvMemoryInstructions.cpp reverted it fails on RADV and
on the RTX 3080; with the change it passes on both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fnrk5Dazjb2tLooVSpdRQq
This commit is contained in:
Jan Šlégl 2026-10-10 15:30:31 +02:00 committed by Hussein Kadhim
parent 5253c499dc
commit 60301adc6d
1 changed files with 41 additions and 2 deletions

View File

@ -21,7 +21,14 @@ constexpr std::uint32_t Iterations = 16;
constexpr std::uint32_t Repeats = 32;
constexpr std::uint32_t LdsDwords = 4;
alignas(256) std::array<std::uint32_t, Threads * 2> Output{};
alignas(256) std::array<std::uint32_t, 4> Unused{};
alignas(256) std::array<std::uint32_t, Threads * 4> Input = [] {
std::array<std::uint32_t, Threads * 4> rows{};
for (std::uint32_t tid = 0; tid < Threads; ++tid) {
rows[tid * 4u] = 0xffffffffu;
rows[tid * 4u + 2u] = 1u;
}
return rows;
}();
template<std::uint32_t Count, std::size_t Head, std::size_t Body, std::size_t Tail>
constexpr auto Unrolled(const std::array<std::uint32_t, Head>& head, const std::array<std::uint32_t, Body>& body, const std::array<std::uint32_t, Tail>& tail) {
@ -125,6 +132,37 @@ alignas(256) constexpr auto ParityCode = Unrolled<1>(
0xbf810000,
}));
alignas(256) constexpr auto LoadedParityCode = Unrolled<1>(
std::to_array<std::uint32_t>({
0x34100083,
0x340a0084,
0x7e020280,
0xe0381000, 0x80000c05,
0x7e0c0280,
0x7e0e0280,
0xd9340000, 0x00000601,
0xbf8c0070,
0xbf8a0000,
0xbe89037e,
}),
std::to_array<std::uint32_t>({
0xbefe03ff, 0x55555555,
0xd9000000, 0x00000c01,
0xbf8cc07f,
0xbefe03ff, 0xaaaaaaaa,
0xd8000004, 0x00000e01,
0xbf8cc07f,
}),
std::to_array<std::uint32_t>({
0xbefe0309,
0xbf8cc07f,
0xbf8a0000,
0xd9d80000, 0x0a000001,
0xbf8cc07f,
0xe0741000, 0x80010a08,
0xbf810000,
}));
std::array<std::uint32_t, 4> BufferDescriptor(const void* data, std::uint32_t bytes) {
const auto address = reinterpret_cast<std::uintptr_t>(data);
return {static_cast<std::uint32_t>(address), static_cast<std::uint32_t>((address >> 32u) & 0xffffu), bytes, 0x31016facu};
@ -146,7 +184,7 @@ void Check(const char* name, std::uint64_t operations, std::uint32_t run) {
void Run(AgcDriver::VulkanDevice& device, std::span<const std::uint32_t> code, const char* name, std::uint64_t operations, std::uint32_t repeats) {
std::vector<std::uint32_t> userData(8, 0u);
const auto input = BufferDescriptor(Unused.data(), static_cast<std::uint32_t>(Unused.size() * 4u));
const auto input = BufferDescriptor(Input.data(), static_cast<std::uint32_t>(Input.size() * 4u));
const auto output = BufferDescriptor(Output.data(), static_cast<std::uint32_t>(Output.size() * 4u));
std::copy(input.begin(), input.end(), userData.begin());
std::copy(output.begin(), output.end(), userData.begin() + 4);
@ -177,6 +215,7 @@ int main() {
Run(*device, UniformCode, "uniform", static_cast<std::uint64_t>(Threads) * Iterations, 1);
Run(*device, DivergentCode, "divergent", static_cast<std::uint64_t>(Threads) / 2u * Iterations, 1);
Run(*device, ParityCode, "split lanes", Threads / 2u, Repeats);
Run(*device, LoadedParityCode, "split lanes with per-lane operands", Threads / 2u, Repeats);
std::puts("lds mixed width atomics tests passed");
return 0;
} catch (const std::exception& error) {