diff --git a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp index 404f3bb05..b18102ba5 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp @@ -45,6 +45,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = { {0x10u, Opcode::S_BCNT1_I32_B64}, {0x13u, Opcode::S_FF1_I32_B32}, {0x14u, Opcode::S_FF1_I32_B64}, + {0x15u, Opcode::S_FLBIT_I32_B32}, {0x16u, Opcode::S_FLBIT_I32_B64}, {0x1bu, Opcode::S_BITSET0_B32}, {0x1du, Opcode::S_BITSET1_B32}, diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index f73dec858..7345b3150 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -476,6 +476,7 @@ std::string InstructionToString(const Instruction& inst) { case Opcode::S_ABS_I32: case Opcode::S_BREV_B32: case Opcode::S_BCNT1_I32_B32: + case Opcode::S_FLBIT_I32_B32: case Opcode::S_FF1_I32_B32: case Opcode::S_FF1_I32_B64: case Opcode::S_NOT_B64: diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 3c5a1bebb..179f7cf26 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -45,6 +45,7 @@ enum class Opcode { S_BCNT1_I32_B64, S_FF1_I32_B32, S_FF1_I32_B64, + S_FLBIT_I32_B32, S_FLBIT_I32_B64, S_BITREPLICATE_B64_B32, S_QUADMASK_B64, @@ -395,6 +396,7 @@ enum class Opcode { V_CMP_GE_U32, V_CMP_T_U32, V_CMP_EQ_I64, + V_CMP_LT_U64, V_CMP_EQ_U64, V_CMP_GT_U64, V_CMP_NE_U64, diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index 5e021acf1..8405c4bcc 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -240,8 +240,9 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = { {0xb5u, Opcode::V_CMPX_NE_I64, false}, {0xd1u, Opcode::V_CMPX_LT_U32}, {0xd2u, Opcode::V_CMPX_EQ_U32}, {0xd3u, Opcode::V_CMPX_LE_U32}, {0xd4u, Opcode::V_CMPX_GT_U32}, {0xd5u, Opcode::V_CMPX_NE_U32}, - {0xd6u, Opcode::V_CMPX_GE_U32}, {0xe2u, Opcode::V_CMP_EQ_U64, false}, - {0xe4u, Opcode::V_CMP_GT_U64, false}, {0xe5u, Opcode::V_CMP_NE_U64, false}, + {0xd6u, Opcode::V_CMPX_GE_U32}, {0xe1u, Opcode::V_CMP_LT_U64, false}, + {0xe2u, Opcode::V_CMP_EQ_U64, false}, {0xe4u, Opcode::V_CMP_GT_U64, false}, + {0xe5u, Opcode::V_CMP_NE_U64, false}, {0xf5u, Opcode::V_CMPX_NE_U64, false}, {0xc9u, Opcode::V_CMP_LT_F16}, {0xcau, Opcode::V_CMP_EQ_F16}, {0xcbu, Opcode::V_CMP_LE_F16}, {0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16}, diff --git a/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp b/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp index ae9ff28d5..06f32fb3f 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp @@ -181,6 +181,7 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) { case O::S_XNOR_B32: return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseXor32, false, true, true); case O::S_FF1_I32_B64: return S_FF1_I32_B64(inst); + case O::S_FLBIT_I32_B32: return V_FFBH_32(inst, false); case O::S_FLBIT_I32_B64: return S_FLBIT_I32_B64(inst); case O::S_BITSET0_B32: return S_BITSET_B32(inst, false); diff --git a/src/graphics/shader/recompiler/frontend/translate/Vector.cpp b/src/graphics/shader/recompiler/frontend/translate/Vector.cpp index 5803b1699..5b730c387 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Vector.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Vector.cpp @@ -99,6 +99,9 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) { case O::V_CMP_EQ_U64: EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, false, false); return true; + case O::V_CMP_LT_U64: + EmitIntegerCompare(inst, IR::ValueOpcode::ULessThan64, IR::Type::U64, false, false); + return true; case O::V_CMP_GT_U64: EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan64, IR::Type::U64, false, false); return true; diff --git a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp index 302126569..eb0275ef7 100644 --- a/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp +++ b/src/graphics/shader/recompiler/ir/passes/ResourceTracking.cpp @@ -139,7 +139,8 @@ public: } std::erase_if(m_program.dynamic_reads, [&](Value value) { const auto* inst = value.Resolve().TryInstruction(); - return std::ranges::any_of(m_indirect_images, [&](const IndirectImagePlan& plan) { + return std::any_of(m_indirect_images.begin(), m_indirect_images.end(), + [&](const IndirectImagePlan& plan) { return std::ranges::find(plan.reads, inst) != plan.reads.end(); }); }); @@ -432,14 +433,16 @@ private: const IndirectImagePlan* FindIndirectImage(const Inst& handle) const { const auto found = - std::ranges::find_if(m_indirect_images, [&](const IndirectImagePlan& plan) { + std::find_if(m_indirect_images.begin(), m_indirect_images.end(), + [&](const IndirectImagePlan& plan) { return plan.handle == &handle; }); return found == m_indirect_images.end() ? nullptr : &*found; } bool IsIndirectPlanningMemory(uint32_t index) const { - return std::ranges::any_of(m_indirect_images, [&](const IndirectImagePlan& plan) { + return std::any_of(m_indirect_images.begin(), m_indirect_images.end(), + [&](const IndirectImagePlan& plan) { return std::ranges::find(plan.memory, index) != plan.memory.end(); }); } diff --git a/src/libs/libAmpr.cpp b/src/libs/libAmpr.cpp index 5ac3fa4d8..c5b4b3ea0 100644 --- a/src/libs/libAmpr.cpp +++ b/src/libs/libAmpr.cpp @@ -2665,6 +2665,7 @@ LIB_DEFINE(InitAmpr_1_Ampr) { LIB_FUNC("dXPaz65HNmk", Ampr::CommandBufferPushMarker); LIB_FUNC("mv0O8Zg0woU", Ampr::CommandBufferPopMarker); LIB_FUNC("DLfoNxTFNVk", Ampr::CommandBufferWaitOnAddress); + LIB_FUNC("V7GQTEeUfhw", Ampr::CommandBufferWaitOnAddress); LIB_FUNC("cQb8Zr8Q0Y0", Ampr::CommandBufferWaitOnCounter); LIB_FUNC("j0+3uJMxYJY", Ampr::CommandBufferWriteAddress); LIB_FUNC("sJXyWHjP-F8", Ampr::CommandBufferWriteAddressOnCompletion); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index d04cf1189..09b72c5d6 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -12960,6 +12960,36 @@ TestCase ScalarFlbitI32B64Gpu() { O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; } +TestCase ScalarFlbitI32B32Gpu() { + using O = ShaderOpcode; + + std::vector code; + AppendSMovLiteral(&code, 0, 0x00000000u); + code.push_back(EncodeSop1(0x15, 20, 0)); + + AppendSMovLiteral(&code, 0, 0x0000ccccu); + code.push_back(EncodeSop1(0x15, 21, 0)); + + AppendSMovLiteral(&code, 0, 0x80000000u); + code.push_back(EncodeSop1(0x15, 22, 0)); + + AppendSMovLiteral(&code, 0, 0x7fffffffu); + code.push_back(EncodeSop1(0x15, 23, 0)); + + AppendStoreSgpr(&code, 20, 0); + AppendStoreSgpr(&code, 21, 1); + AppendStoreSgpr(&code, 22, 2); + AppendStoreSgpr(&code, 23, 3); + AppendEnd(&code); + + return {"ScalarFlbitI32B32Gpu", + code, + {}, + {0xffffffffu, 16, 0, 1}, + {O::S_MOV_B32, O::S_FLBIT_I32_B32, O::V_MOV_B32, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; +} + TestCase ScalarSaveExecOps() { using O = ShaderOpcode; @@ -16091,6 +16121,36 @@ TestCase VectorVop3CompareGtU64OnGpu() { return test; } +TestCase VectorVopcCompareLtU64OnGpu() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovU32(&code, 0, 5); + AppendVMovU32(&code, 1, 0); + AppendVMovU32(&code, 2, 1); + + AppendSMovLiteral(&code, 4, 4); + AppendSMovLiteral(&code, 5, 0); + code.push_back(EncodeVopc(0xe1, 4, 0)); + code.push_back(EncodeVop2(0x01, 3, InlineU32(0), 2)); + AppendStoreVgpr(&code, 3, 0); + + AppendSMovLiteral(&code, 4, 6); + code.push_back(EncodeVopc(0xe1, 4, 0)); + code.push_back(EncodeVop2(0x01, 4, InlineU32(0), 2)); + AppendStoreVgpr(&code, 4, 1); + AppendEnd(&code); + + TestCase test{"VectorVopcCompareLtU64OnGpu", + code, + {}, + {1, 0}, + {O::V_MOV_B32, O::S_MOV_B32, O::V_CMP_LT_U64, + O::V_CNDMASK_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; + test.decoded_counts = {{"V_CMP_LT_U64 vcc_lo, s4, v0", 2}}; + return test; +} + TestCase VectorVop3CompareEqI64OnGpu() { using O = ShaderOpcode; @@ -21148,6 +21208,7 @@ std::vector MakeCases() { AddCase(ScalarMovB32SpecialAliases); AddCase(ScalarQuadmaskB64); AddCase(ScalarFlbitI32B64Gpu); + AddCase(ScalarFlbitI32B32Gpu); AddCase(ScalarSaveExecOps); AddCase(ScalarOrn2SaveexecUsesSourceOrNotExec); AddCase(ScalarGetpcWritesNextInstructionPc); @@ -21238,6 +21299,7 @@ std::vector MakeCases() { AddCase(VectorVop3CompareEqI64OnGpu); AddCase(VectorVop3CompareEqU64OnGpu); AddCase(VectorVop3CompareGtU64OnGpu); + AddCase(VectorVopcCompareLtU64OnGpu); AddCase(VectorVop3CompareNeU64OnGpu); AddCase(VectorVopcCmpxNeU64CapturedExecMask); AddCase(VectorVop3CmpxNeI64CapturedExecMask); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 5945c95b1..df7df3b17 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -3969,6 +3969,37 @@ void TestNewShaderDecoderArchitecture() { cmp_eq_u64.src1.kind == OperandKind::VccLo, "decoder rejected the captured VOP3 V_CMP_EQ_U64 instruction"); + const uint32_t completed_pr_opcodes[] = { + EncodeSop1(0x15, 0, 1), // s_flbit_i32_b32 s0, s1 + EncodeVopc(0xe1, 128, 0), // v_cmp_lt_u64 vcc, 0, v[0:1] + EncodeSopp(0x01, 0), + }; + Instruction flbit_i32_b32; + ShaderRecompiler::Decoder::DecodeInstruction(completed_pr_opcodes, 0u, + flbit_i32_b32); + Instruction cmp_lt_u64; + ShaderRecompiler::Decoder::DecodeInstruction(completed_pr_opcodes, 1u, + cmp_lt_u64); + Check(flbit_i32_b32.family == Family::SOP1 && + flbit_i32_b32.opcode == Opcode::S_FLBIT_I32_B32 && + flbit_i32_b32.dst.kind == OperandKind::Sgpr && + flbit_i32_b32.dst.reg == 0u && + flbit_i32_b32.src0.kind == OperandKind::Sgpr && + flbit_i32_b32.src0.reg == 1u && + cmp_lt_u64.family == Family::VOPC && + cmp_lt_u64.opcode == Opcode::V_CMP_LT_U64 && + cmp_lt_u64.dst.kind == OperandKind::VccLo, + "decoder rejected completed PR #427 scalar/vector opcodes"); + + const auto completed_options = MakeCompileOptions(ShaderType::Compute); + const auto completed_result = + ShaderRecompiler::Recompile(completed_pr_opcodes, completed_options); + Check(Common::ContainsStr(completed_result.decoded_dump, + "S_FLBIT_I32_B32 s0, s1") && + Common::ContainsStr(completed_result.decoded_dump, + "V_CMP_LT_U64 vcc_lo, 0, v0"), + "completed PR #427 opcodes were absent from the decoded shader"); + const uint32_t ffbh_i32_code[] = {0x7e1c770eu}; Instruction ffbh_i32; ShaderRecompiler::Decoder::DecodeInstruction(ffbh_i32_code, 0u, ffbh_i32);