shader: support returning 32-bit LDS compare-exchange (DS_CMPST_RTN_B32) (#1578)

* shader: support DS_CMPST_RTN_B32

Assassin's Creed Valhalla (PPSA01490, #281) stops on DS opcode 0x30 in a
compute shader. DS compares DATA and stores DATA2, the opposite of
BUFFER_ATOMIC_CMPSWAP, so the 32-bit atomic path swaps the two for this
opcode, as the 64-bit form does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* shader: reject unsupported GDS compare-store variant

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
authored and GitHub committed 2026-10-17 04:37:16 +02:00
1 parent 0fd41ae206
commit e93b4b0378
10 files changed
+97 -3

No files matched your search

+19
View File
@@ -8119,6 +8119,24 @@ void TestDsReturningAtomic64Decoder() {
"captured DS_CMPST_RTN_B64 lost its comparison/replacement pairs or aliases");
}
void TestDsCompareStore32Decoder() {
using namespace ShaderRecompiler::Decoder;
// CS04b812daaacd532f pc 0x3e8 (AC Valhalla, #281).
const uint32_t words[] = {0xd8c00000u, 0x04130504u};
Instruction decoded;
DecodeInstruction(words, 0u, decoded);
Check(decoded.opcode == Opcode::DS_CMPST_RTN_B32 && decoded.word_count == 2u &&
decoded.data_dwords == 1u && decoded.src_count == 3u && decoded.src0.reg == 4u &&
decoded.src1.reg == 5u && decoded.src2.reg == 19u && decoded.dst.reg == 4u &&
decoded.offset == 0u && !decoded.gds,
"captured DS_CMPST_RTN_B32 lost its comparison/replacement order or aliases");
const uint32_t gds_words[] = {words[0] | (1u << 17u), words[1]};
DecodeInstruction(gds_words, 0u, decoded);
Check(decoded.opcode == Opcode::UNSUPPORTED && decoded.word_count == 2u && decoded.gds,
"DS_CMPST_RTN_B32 must reject the unimplemented GDS variant");
}
void TestDsFloatMinMaxDecoder() {
using namespace ShaderRecompiler::Decoder;
for (bool max_value : {false, true}) {
@@ -16480,6 +16498,7 @@ int main() {
TestScalarAshrI64Decoder();
TestImageAtomicWidthDecoder();
TestDsReturningAtomic64Decoder();
TestDsCompareStore32Decoder();
TestDsFloatMinMaxDecoder();
TestNewShaderDecoderArchitecture();
TestImageAddressOperands();