From 715539804be2141a9ec53969b4bcf96326d7cb08 Mon Sep 17 00:00:00 2001 From: GodsWill Dev <56268269+Techx3@users.noreply.github.com> Date: Sat, 29 Aug 2026 02:28:28 -0400 Subject: [PATCH] shader: accept SDWA for VOP1 bit operations (#360) Allow byte, word, and full-dword SDWA source selection for V_NOT_B32 and V_FFBL_B32. Add captured instruction tests that verify decoding, IR extraction, SPIR-V generation, and runtime results. Co-authored-by: SueryRD --- .../frontend/decode/VectorAluOps.cpp | 2 + tests/ShaderRecompilerComputeTests.cpp | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index 8201595b..b324b07e 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -515,6 +515,8 @@ constexpr Vop1SdwaRule VOP1_SDWA_RULES[] = { {Opcode::V_CVT_F32_U32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false}, {Opcode::V_CVT_F32_I32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false}, {Opcode::V_CVT_F32_UBYTE0, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false}, + {Opcode::V_NOT_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false}, + {Opcode::V_FFBL_B32, SdwaSelBytes() | SdwaSelWords() | SdwaSelFull(), 0, 0, false}, {Opcode::V_CVT_F32_F16, SdwaSelWords() | SdwaSelFull(), 0, 0, true}, {Opcode::V_CVT_F16_F32, SdwaSelFull(), SdwaSelWords(), SdwaSelFull(), false}, {Opcode::V_CVT_F16_U16, SdwaSelWords() | SdwaSelFull(), SdwaSelWords(), diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 2b308a65..c0df2b88 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -13355,6 +13355,52 @@ TestCase VectorIntegerOps() { O::S_ENDPGM}}; } +TestCase Vop1SdwaFfblCapturedHighWordSource() { + using O = ShaderOpcode; + + std::vector code; + AppendBufferLoadDword(&code, 2, 30); + code.push_back(0x7e2074f9u); + code.push_back(0x00050602u); // v_ffbl_b32 v16, v2.word1 + AppendStoreVgpr(&code, 16, 0); + AppendEnd(&code); + + TestCase test; + test.name = "Vop1SdwaFfblCapturedHighWordSource"; + test.code = std::move(code); + test.initial = {0x00400000u}; + test.expected = {6u}; + test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_FFBL_B32, O::BUFFER_STORE_DWORD, + O::S_ENDPGM}; + test.decoded_counts = {{"V_FFBL_B32 v16, v2.sdwa(sel=5,sext=0)", 1}}; + test.ir_counts = {{" = BitFieldUExtract ", 1}, {" = FindILsb32 ", 1}}; + test.required_spirv = {"OpBitFieldUExtract"}; + return test; +} + +TestCase Vop1SdwaNotCapturedByte0Source() { + using O = ShaderOpcode; + + std::vector code; + AppendBufferLoadDword(&code, 2, 30); + code.push_back(0x7e046ef9u); + code.push_back(0x00000602u); // v_not_b32 v2, v2.byte0 + AppendStoreVgpr(&code, 2, 0); + AppendEnd(&code); + + TestCase test; + test.name = "Vop1SdwaNotCapturedByte0Source"; + test.code = std::move(code); + test.initial = {0x12345678u}; + test.expected = {0xffffff87u}; + test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_NOT_B32, O::BUFFER_STORE_DWORD, + O::S_ENDPGM}; + test.decoded_counts = {{"V_NOT_B32 v2, v2.sdwa(sel=0,sext=0)", 1}}; + test.ir_counts = {{" = BitFieldUExtract ", 1}, {" = BitwiseNot32 ", 1}}; + test.required_spirv = {"OpBitFieldUExtract", "OpNot"}; + return test; +} + TestCase Vop2SdwaSubNcExactByte2Destination() { using O = ShaderOpcode; @@ -20350,6 +20396,8 @@ std::vector MakeCases() { AddCase(VectorMoves); AddCase(VectorVop3MoveAppliesFloatSourceModifiers); AddCase(VectorIntegerOps); + AddCase(Vop1SdwaFfblCapturedHighWordSource); + AddCase(Vop1SdwaNotCapturedByte0Source); AddCase(Vop2SdwaSubNcExactByte2Destination); AddCase(Vop2SdwaAddNcCapturedHighWordDestination); AddCase(Vop2SdwaAshrrevCapturedWord0SignExtends);