mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
shader: took fixes from PR 427
- apply c8f34f9's ResourceTracking portability fix
- complete V_CMP_LT_U64 and S_FLBIT_I32_B32 support
- add the sceAmprCommandBufferWaitOnAddress NID from f625a47
- add decoder and compute tests for both shader operations
Co-authored-by: Mac <me@itsmemac.com>
This commit is contained in:
@@ -45,6 +45,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
|||||||
{0x10u, Opcode::S_BCNT1_I32_B64},
|
{0x10u, Opcode::S_BCNT1_I32_B64},
|
||||||
{0x13u, Opcode::S_FF1_I32_B32},
|
{0x13u, Opcode::S_FF1_I32_B32},
|
||||||
{0x14u, Opcode::S_FF1_I32_B64},
|
{0x14u, Opcode::S_FF1_I32_B64},
|
||||||
|
{0x15u, Opcode::S_FLBIT_I32_B32},
|
||||||
{0x16u, Opcode::S_FLBIT_I32_B64},
|
{0x16u, Opcode::S_FLBIT_I32_B64},
|
||||||
{0x1bu, Opcode::S_BITSET0_B32},
|
{0x1bu, Opcode::S_BITSET0_B32},
|
||||||
{0x1du, Opcode::S_BITSET1_B32},
|
{0x1du, Opcode::S_BITSET1_B32},
|
||||||
|
|||||||
@@ -476,6 +476,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||||||
case Opcode::S_ABS_I32:
|
case Opcode::S_ABS_I32:
|
||||||
case Opcode::S_BREV_B32:
|
case Opcode::S_BREV_B32:
|
||||||
case Opcode::S_BCNT1_I32_B32:
|
case Opcode::S_BCNT1_I32_B32:
|
||||||
|
case Opcode::S_FLBIT_I32_B32:
|
||||||
case Opcode::S_FF1_I32_B32:
|
case Opcode::S_FF1_I32_B32:
|
||||||
case Opcode::S_FF1_I32_B64:
|
case Opcode::S_FF1_I32_B64:
|
||||||
case Opcode::S_NOT_B64:
|
case Opcode::S_NOT_B64:
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ enum class Opcode {
|
|||||||
S_BCNT1_I32_B64,
|
S_BCNT1_I32_B64,
|
||||||
S_FF1_I32_B32,
|
S_FF1_I32_B32,
|
||||||
S_FF1_I32_B64,
|
S_FF1_I32_B64,
|
||||||
|
S_FLBIT_I32_B32,
|
||||||
S_FLBIT_I32_B64,
|
S_FLBIT_I32_B64,
|
||||||
S_BITREPLICATE_B64_B32,
|
S_BITREPLICATE_B64_B32,
|
||||||
S_QUADMASK_B64,
|
S_QUADMASK_B64,
|
||||||
@@ -395,6 +396,7 @@ enum class Opcode {
|
|||||||
V_CMP_GE_U32,
|
V_CMP_GE_U32,
|
||||||
V_CMP_T_U32,
|
V_CMP_T_U32,
|
||||||
V_CMP_EQ_I64,
|
V_CMP_EQ_I64,
|
||||||
|
V_CMP_LT_U64,
|
||||||
V_CMP_EQ_U64,
|
V_CMP_EQ_U64,
|
||||||
V_CMP_GT_U64,
|
V_CMP_GT_U64,
|
||||||
V_CMP_NE_U64,
|
V_CMP_NE_U64,
|
||||||
|
|||||||
@@ -240,8 +240,9 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
|||||||
{0xb5u, Opcode::V_CMPX_NE_I64, false}, {0xd1u, Opcode::V_CMPX_LT_U32},
|
{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},
|
{0xd2u, Opcode::V_CMPX_EQ_U32}, {0xd3u, Opcode::V_CMPX_LE_U32},
|
||||||
{0xd4u, Opcode::V_CMPX_GT_U32}, {0xd5u, Opcode::V_CMPX_NE_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},
|
{0xd6u, Opcode::V_CMPX_GE_U32}, {0xe1u, Opcode::V_CMP_LT_U64, false},
|
||||||
{0xe4u, Opcode::V_CMP_GT_U64, false}, {0xe5u, Opcode::V_CMP_NE_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},
|
{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},
|
{0xcau, Opcode::V_CMP_EQ_F16}, {0xcbu, Opcode::V_CMP_LE_F16},
|
||||||
{0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16},
|
{0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16},
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) {
|
|||||||
case O::S_XNOR_B32:
|
case O::S_XNOR_B32:
|
||||||
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseXor32, false, true, true);
|
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseXor32, false, true, true);
|
||||||
case O::S_FF1_I32_B64: return S_FF1_I32_B64(inst);
|
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_FLBIT_I32_B64: return S_FLBIT_I32_B64(inst);
|
||||||
|
|
||||||
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
|
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
|
|||||||
case O::V_CMP_EQ_U64:
|
case O::V_CMP_EQ_U64:
|
||||||
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, false, false);
|
EmitIntegerCompare(inst, IR::ValueOpcode::IEqual64, IR::Type::U64, false, false);
|
||||||
return true;
|
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:
|
case O::V_CMP_GT_U64:
|
||||||
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan64, IR::Type::U64, false, false);
|
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThan64, IR::Type::U64, false, false);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ public:
|
|||||||
}
|
}
|
||||||
std::erase_if(m_program.dynamic_reads, [&](Value value) {
|
std::erase_if(m_program.dynamic_reads, [&](Value value) {
|
||||||
const auto* inst = value.Resolve().TryInstruction();
|
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();
|
return std::ranges::find(plan.reads, inst) != plan.reads.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -432,14 +433,16 @@ private:
|
|||||||
|
|
||||||
const IndirectImagePlan* FindIndirectImage(const Inst& handle) const {
|
const IndirectImagePlan* FindIndirectImage(const Inst& handle) const {
|
||||||
const auto found =
|
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 plan.handle == &handle;
|
||||||
});
|
});
|
||||||
return found == m_indirect_images.end() ? nullptr : &*found;
|
return found == m_indirect_images.end() ? nullptr : &*found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsIndirectPlanningMemory(uint32_t index) const {
|
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();
|
return std::ranges::find(plan.memory, index) != plan.memory.end();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2665,6 +2665,7 @@ LIB_DEFINE(InitAmpr_1_Ampr) {
|
|||||||
LIB_FUNC("dXPaz65HNmk", Ampr::CommandBufferPushMarker);
|
LIB_FUNC("dXPaz65HNmk", Ampr::CommandBufferPushMarker);
|
||||||
LIB_FUNC("mv0O8Zg0woU", Ampr::CommandBufferPopMarker);
|
LIB_FUNC("mv0O8Zg0woU", Ampr::CommandBufferPopMarker);
|
||||||
LIB_FUNC("DLfoNxTFNVk", Ampr::CommandBufferWaitOnAddress);
|
LIB_FUNC("DLfoNxTFNVk", Ampr::CommandBufferWaitOnAddress);
|
||||||
|
LIB_FUNC("V7GQTEeUfhw", Ampr::CommandBufferWaitOnAddress);
|
||||||
LIB_FUNC("cQb8Zr8Q0Y0", Ampr::CommandBufferWaitOnCounter);
|
LIB_FUNC("cQb8Zr8Q0Y0", Ampr::CommandBufferWaitOnCounter);
|
||||||
LIB_FUNC("j0+3uJMxYJY", Ampr::CommandBufferWriteAddress);
|
LIB_FUNC("j0+3uJMxYJY", Ampr::CommandBufferWriteAddress);
|
||||||
LIB_FUNC("sJXyWHjP-F8", Ampr::CommandBufferWriteAddressOnCompletion);
|
LIB_FUNC("sJXyWHjP-F8", Ampr::CommandBufferWriteAddressOnCompletion);
|
||||||
|
|||||||
@@ -12960,6 +12960,36 @@ TestCase ScalarFlbitI32B64Gpu() {
|
|||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarFlbitI32B32Gpu() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> 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() {
|
TestCase ScalarSaveExecOps() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -16091,6 +16121,36 @@ TestCase VectorVop3CompareGtU64OnGpu() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase VectorVopcCompareLtU64OnGpu() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> 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() {
|
TestCase VectorVop3CompareEqI64OnGpu() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -21148,6 +21208,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarMovB32SpecialAliases);
|
AddCase(ScalarMovB32SpecialAliases);
|
||||||
AddCase(ScalarQuadmaskB64);
|
AddCase(ScalarQuadmaskB64);
|
||||||
AddCase(ScalarFlbitI32B64Gpu);
|
AddCase(ScalarFlbitI32B64Gpu);
|
||||||
|
AddCase(ScalarFlbitI32B32Gpu);
|
||||||
AddCase(ScalarSaveExecOps);
|
AddCase(ScalarSaveExecOps);
|
||||||
AddCase(ScalarOrn2SaveexecUsesSourceOrNotExec);
|
AddCase(ScalarOrn2SaveexecUsesSourceOrNotExec);
|
||||||
AddCase(ScalarGetpcWritesNextInstructionPc);
|
AddCase(ScalarGetpcWritesNextInstructionPc);
|
||||||
@@ -21238,6 +21299,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(VectorVop3CompareEqI64OnGpu);
|
AddCase(VectorVop3CompareEqI64OnGpu);
|
||||||
AddCase(VectorVop3CompareEqU64OnGpu);
|
AddCase(VectorVop3CompareEqU64OnGpu);
|
||||||
AddCase(VectorVop3CompareGtU64OnGpu);
|
AddCase(VectorVop3CompareGtU64OnGpu);
|
||||||
|
AddCase(VectorVopcCompareLtU64OnGpu);
|
||||||
AddCase(VectorVop3CompareNeU64OnGpu);
|
AddCase(VectorVop3CompareNeU64OnGpu);
|
||||||
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
||||||
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
||||||
|
|||||||
@@ -3969,6 +3969,37 @@ void TestNewShaderDecoderArchitecture() {
|
|||||||
cmp_eq_u64.src1.kind == OperandKind::VccLo,
|
cmp_eq_u64.src1.kind == OperandKind::VccLo,
|
||||||
"decoder rejected the captured VOP3 V_CMP_EQ_U64 instruction");
|
"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};
|
const uint32_t ffbh_i32_code[] = {0x7e1c770eu};
|
||||||
Instruction ffbh_i32;
|
Instruction ffbh_i32;
|
||||||
ShaderRecompiler::Decoder::DecodeInstruction(ffbh_i32_code, 0u, ffbh_i32);
|
ShaderRecompiler::Decoder::DecodeInstruction(ffbh_i32_code, 0u, ffbh_i32);
|
||||||
|
|||||||
Reference in New Issue
Block a user