diff --git a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp index ee22e6c0f..8320a2fbb 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp @@ -27,27 +27,17 @@ constexpr OpcodeMap SOP2_OPS[] = { }; constexpr OpcodeMap SOP1_OPS[] = { - {0x03u, Opcode::SMovB32}, - {0x04u, Opcode::SMovB64}, - {0x07u, Opcode::SNotB32}, - {0x08u, Opcode::SNotB64}, - {0x0au, Opcode::SWqmB64}, - {0x0bu, Opcode::SBrevB32}, - {0x0fu, Opcode::SBcnt1I32B32}, - {0x10u, Opcode::SBcnt1I32B64}, - {0x13u, Opcode::SFf1I32B32}, - {0x16u, Opcode::SFlbitI32B64}, - {0x1bu, Opcode::SBitset0B32}, - {0x1du, Opcode::SBitset1B32}, - {0x1fu, Opcode::SGetpcB64}, - {0x20u, Opcode::SSetpcB64}, - {0x24u, Opcode::SAndSaveexecB64}, - {0x28u, Opcode::SOrn2SaveexecB64}, - {0x34u, Opcode::SAbsI32}, - {0x37u, Opcode::SAndn1SaveexecB64}, - {0x3bu, Opcode::SBitreplicateB64B32}, - {0x3cu, Opcode::SAndSaveexecB32}, - {0x44u, Opcode::SAndn1SaveexecB32}, + {0x03u, Opcode::SMovB32}, {0x04u, Opcode::SMovB64}, + {0x07u, Opcode::SNotB32}, {0x08u, Opcode::SNotB64}, + {0x0au, Opcode::SWqmB64}, {0x0bu, Opcode::SBrevB32}, + {0x0fu, Opcode::SBcnt1I32B32}, {0x10u, Opcode::SBcnt1I32B64}, + {0x13u, Opcode::SFf1I32B32}, {0x14u, Opcode::SFf1I32B64}, + {0x16u, Opcode::SFlbitI32B64}, {0x1bu, Opcode::SBitset0B32}, + {0x1du, Opcode::SBitset1B32}, {0x1fu, Opcode::SGetpcB64}, + {0x20u, Opcode::SSetpcB64}, {0x24u, Opcode::SAndSaveexecB64}, + {0x28u, Opcode::SOrn2SaveexecB64}, {0x34u, Opcode::SAbsI32}, + {0x37u, Opcode::SAndn1SaveexecB64}, {0x3bu, Opcode::SBitreplicateB64B32}, + {0x3cu, Opcode::SAndSaveexecB32}, {0x44u, Opcode::SAndn1SaveexecB32}, }; constexpr OpcodeMap SOPC_OPS[] = { diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index 7d41f8cc6..10aeda7ab 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -446,6 +446,7 @@ std::string OpcodeToString(Opcode opcode) { case Opcode::SBcnt1I32B32: return "s_bcnt1_i32_b32"; case Opcode::SBcnt1I32B64: return "s_bcnt1_i32_b64"; case Opcode::SFf1I32B32: return "s_ff1_i32_b32"; + case Opcode::SFf1I32B64: return "s_ff1_i32_b64"; case Opcode::SFlbitI32B64: return "s_flbit_i32_b64"; case Opcode::SBitreplicateB64B32: return "s_bitreplicate_b64_b32"; case Opcode::SGetpcB64: return "s_getpc_b64"; @@ -1017,6 +1018,7 @@ std::string InstructionToString(const Instruction& inst) { case Opcode::SBrevB32: case Opcode::SBcnt1I32B32: case Opcode::SFf1I32B32: + case Opcode::SFf1I32B64: case Opcode::SNotB64: case Opcode::SWqmB64: case Opcode::SAndSaveexecB32: diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 98ce6b985..0f5e1d313 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -43,6 +43,7 @@ enum class Opcode { SBcnt1I32B32, SBcnt1I32B64, SFf1I32B32, + SFf1I32B64, SFlbitI32B64, SBitreplicateB64B32, SGetpcB64, diff --git a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp index c1a88958c..8a14ac055 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp @@ -320,6 +320,16 @@ bool Translator::TranslateComposedInteger(const IR::Instruction& inst) { result = ir.BitwiseXor(ir.BitwiseXor(ReadU32(inst.src[0]), ReadU32(inst.src[1])), ReadU32(inst.src[2])); break; + case IR::Opcode::FindLsbU64: { + const auto source = UnpackU64(ReadU64(inst.src[0])); + const auto low_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]})); + const auto high_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]})); + const auto high_position = ir.IAdd(high_lsb, IR::U32(IR::Value(32u))); + result = ir.Select(ir.INotEqual(source[0], IR::U32(IR::Value(0u))), low_lsb, + ir.Select(ir.INotEqual(source[1], IR::U32(IR::Value(0u))), + high_position, IR::U32(IR::Value(0xffffffffu)))); + break; + } case IR::Opcode::FindMsbFromHighU32: { const auto source = ReadU32(inst.src[0]); const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb32, {source})); diff --git a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp index 2dabf41d2..c6d189d26 100644 --- a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp +++ b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp @@ -25,6 +25,7 @@ constexpr LowerMap LOWER_OPS[] = { {Decoder::Opcode::SBcnt1I32B32, Opcode::BitCountU32}, {Decoder::Opcode::SBcnt1I32B64, Opcode::BitCountU64}, {Decoder::Opcode::SFf1I32B32, Opcode::FindLsbU32}, + {Decoder::Opcode::SFf1I32B64, Opcode::FindLsbU64}, {Decoder::Opcode::SFlbitI32B64, Opcode::FindMsbFromHighU64}, {Decoder::Opcode::SBitreplicateB64B32, Opcode::BitReplicateB64B32}, {Decoder::Opcode::SNotB32, Opcode::BitwiseNotU32}, diff --git a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc index a7fa629d4..446c976b7 100644 --- a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc +++ b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.inc @@ -82,6 +82,7 @@ IR_OPCODE(BitCountAddU32, General, ExtendedInteger) IR_OPCODE(MaskedBitCountLowU32, General, ExtendedInteger) IR_OPCODE(MaskedBitCountHighU32, General, ExtendedInteger) IR_OPCODE(FindLsbU32, General, SimpleInteger) +IR_OPCODE(FindLsbU64, General, ComposedInteger) IR_OPCODE(FindMsbFromHighU32, General, ComposedInteger) IR_OPCODE(FindMsbFromHighU64, General, ComposedInteger) IR_OPCODE(BitFieldMaskU32, General, ExtendedInteger) diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index d5b2701cf..aecb36604 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -11080,6 +11080,19 @@ TestCase ScalarBitfieldPack() { code.push_back(EncodeSop2(0x0a, 17, InlineU32(1), InlineU32(0))); code.push_back(EncodeSopc(0x0c, InlineU32(4), InlineU32(1))); code.push_back(EncodeSop2(0x0a, 18, InlineU32(1), InlineU32(0))); + AppendSMovLiteral(&code, 25, 0u); + AppendSMovLiteral(&code, 26, 0x00000100u); + code.push_back(EncodeSopc(0x06, InlineU32(0), InlineU32(1))); + code.push_back(EncodeSop1(0x14, 31, 25)); + code.push_back(EncodeSop2(0x0a, 34, InlineU32(1), InlineU32(0))); + AppendSMovLiteral(&code, 27, 0x00000020u); + AppendSMovLiteral(&code, 28, 0x00000100u); + code.push_back(EncodeSopc(0x06, InlineU32(1), InlineU32(1))); + code.push_back(EncodeSop1(0x14, 32, 27)); + code.push_back(EncodeSop2(0x0a, 35, InlineU32(1), InlineU32(0))); + AppendSMovLiteral(&code, 29, 0u); + AppendSMovLiteral(&code, 30, 0u); + code.push_back(EncodeSop1(0x14, 33, 29)); AppendStoreSgpr(&code, 1, 0); AppendStoreSgpr(&code, 3, 1); @@ -11095,15 +11108,22 @@ TestCase ScalarBitfieldPack() { AppendStoreSgpr(&code, 15, 12); AppendStoreSgpr(&code, 17, 13); AppendStoreSgpr(&code, 18, 14); + AppendStoreSgpr(&code, 31, 15); + AppendStoreSgpr(&code, 32, 16); + AppendStoreSgpr(&code, 33, 17); + AppendStoreSgpr(&code, 34, 18); + AppendStoreSgpr(&code, 35, 19); AppendEnd(&code); return {"ScalarBitfieldPack", code, {}, {0xf0000000u, 8, 9, 1, 0, 0, 0x0000000fu, 0, 0x00000f00u, 0x0000000fu, - 0xddddbbbbu, 0xccccbbbbu, 0xccccaaaau, 1, 1}, + 0xddddbbbbu, 0xccccbbbbu, 0xccccaaaau, 1, 1, 40, 5, 0xffffffffu, 0, + 1}, {O::SMovB32, O::SBrevB32, O::SBcnt1I32B32, O::SBcnt1I32B64, - O::SBitreplicateB64B32, O::SBfmB32, O::SBfeU32, O::SPackLlB32B16, + O::SFf1I32B64, O::SBitreplicateB64B32, O::SBfmB32, O::SBfeU32, + O::SPackLlB32B16, O::SPackLhB32B16, O::SPackHhB32B16, O::SBitcmp0B32, O::SBitcmp1B32, O::SCselectB32, O::VMovB32, O::BufferStoreDword, O::SEndpgm}}; } @@ -20269,6 +20289,11 @@ int main(int argc, char **argv) { RunCase(&vulkan, VectorAlignByteUsesFiveBitByteOffset()); return 0; } + if (argc == 2 && std::strcmp(argv[1], "--sff1-b64-only") == 0) { + VulkanHarness vulkan; + RunCase(&vulkan, ScalarBitfieldPack()); + return 0; + } if (argc == 2 && std::strcmp(argv[1], "--context-state-only") == 0) { VulkanHarness vulkan; CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer()); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 0714ad369..ad63afa3d 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -2931,6 +2931,7 @@ void TestNewShaderRecompilerScalarB64Alu() { EncodeSop2(0x21, 26, 24, 0), // s_lshr_b64 s[26:27], s[24:25], s0 EncodeSop2(0x25, 28, 132, 130), // s_bfm_b64 s[28:29], 4, 2 EncodeSop1(0x10, 30, 26), // s_bcnt1_i32_b64 s30, s[26:27] + EncodeSop1(0x14, 31, 26), // s_ff1_i32_b64 s31, s[26:27] EncodeSop1(0x16, 106, 26), // s_flbit_i32_b64 vcc_lo, s[26:27] EncodeSop1(0x3b, 32, 30), // s_bitreplicate_b64_b32 s[32:33], s30 EncodeSop2(0x29, 34, 32, 255), // s_bfe_u64 s[34:35], s[32:33], 0x00040002 @@ -2989,6 +2990,8 @@ void TestNewShaderRecompilerScalarB64Alu() { "new decoder did not decode old-backed S_BFM_B64"); Check(Common::ContainsStr(result.decoded_dump, "s_bcnt1_i32_b64 s30, s26"), "new decoder did not decode old-backed S_BCNT1_I32_B64"); + Check(Common::ContainsStr(result.decoded_dump, "s_ff1_i32_b64 s31, s26"), + "new decoder did not decode RDNA2 S_FF1_I32_B64"); Check(Common::ContainsStr(result.decoded_dump, "s_flbit_i32_b64 vcc_lo, s26"), "new decoder did not decode RDNA2 S_FLBIT_I32_B64"); Check(Common::ContainsStr(result.decoded_dump, @@ -3042,6 +3045,8 @@ void TestNewShaderRecompilerScalarB64Alu() { "S_BFM_B64 did not lower to paired-dword IR"); Check(Common::ContainsStr(result.ir_dump, "BitCountU64 s30, s26"), "S_BCNT1_I32_B64 did not lower to paired-source bit count IR"); + Check(Common::ContainsStr(result.ir_dump, "FindLsbU64 s31, s26"), + "S_FF1_I32_B64 did not lower to paired-source bit search IR"); Check(Common::ContainsStr(result.ir_dump, "FindMsbFromHighU64 vcc_lo, s26"), "S_FLBIT_I32_B64 did not lower to paired-source leading-zero IR"); Check(Common::ContainsStr(result.ir_dump, "BitReplicateB64B32 s32, s30"),