mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
agc: implement branch target patching and packet size queries
This commit is contained in:
@@ -41818,6 +41818,56 @@ void CheckPm4IndirectControlFlow(RenderContext &renderer) {
|
||||
}
|
||||
}
|
||||
|
||||
std::array<uint32_t, 5> cx_packet{};
|
||||
CommandBufferLayout cx_dcb{cx_packet.data(), cx_packet.data() + cx_packet.size(),
|
||||
cx_packet.data(), cx_packet.data() + cx_packet.size(),
|
||||
nullptr, nullptr, 0};
|
||||
const ShaderRegister cx_register{Pm4::CB_TARGET_MASK, 0x76543210u};
|
||||
Require(name, "indirect context packet size",
|
||||
Gen5::AgcDcbSetCxRegistersIndirectGetSize() == sizeof(cx_packet) &&
|
||||
Gen5::AgcDcbSetCxRegistersIndirect(
|
||||
reinterpret_cast<Gen5::CommandBuffer *>(&cx_dcb), &cx_register, 1) ==
|
||||
cx_packet.data() && cx_dcb.cursor_up == cx_dcb.top,
|
||||
"indirect Cx size did not match the emitted command buffer");
|
||||
|
||||
std::array<uint32_t, 14> patched_branch{};
|
||||
CommandBufferLayout branch_dcb{
|
||||
patched_branch.data(), patched_branch.data() + patched_branch.size(),
|
||||
patched_branch.data(), patched_branch.data() + patched_branch.size(),
|
||||
nullptr, nullptr, 0};
|
||||
Require(name, "branch packet size",
|
||||
Gen5::AgcCbBranchGetSize() == sizeof(patched_branch) &&
|
||||
Gen5::AgcCbBranch(reinterpret_cast<Gen5::CommandBuffer *>(&branch_dcb),
|
||||
1, 0, &condition, 0, 0, 0, nullptr, 0,
|
||||
3, else_commands.data(), else_commands.size()) ==
|
||||
patched_branch.data() && branch_dcb.cursor_up == branch_dcb.top,
|
||||
"branch size did not match the emitted command buffer");
|
||||
patched_branch[8] = 3;
|
||||
patched_branch[10] = 0xc5a00000u;
|
||||
const auto unpatched = patched_branch;
|
||||
Require(name, "patched indirect context branch",
|
||||
Gen5::AgcBranchPatchSetThenTarget(patched_branch.data(), 2,
|
||||
cx_packet.data(), cx_packet.size()) == 0 &&
|
||||
(patched_branch[8] & 3u) == 3u &&
|
||||
patched_branch[10] == 0xe5a00005u &&
|
||||
std::equal(patched_branch.begin(), patched_branch.begin() + 8,
|
||||
unpatched.begin()) &&
|
||||
std::equal(patched_branch.begin() + 11, patched_branch.end(),
|
||||
unpatched.begin() + 11),
|
||||
"branch target patch lost reserved fields or changed the condition/else target");
|
||||
Pm4Execution patched_execution;
|
||||
Require(name, "patched branch execution",
|
||||
processor.Process(patched_execution, patched_branch) == Pm4ProcessResult::Complete &&
|
||||
processor.GetCtx().GetRenderTargetMask() == cx_register.value,
|
||||
"patched branch did not fetch and apply its indirect context registers");
|
||||
patched_branch[0] = KYTY_PM4(14, Pm4::IT_NOP, 0);
|
||||
const auto mismatched = patched_branch;
|
||||
Require(name, "branch packet mismatch",
|
||||
Gen5::AgcBranchPatchSetThenTarget(patched_branch.data(), 0,
|
||||
then_commands.data(), then_commands.size()) ==
|
||||
static_cast<int>(0x8a6c000cu) && patched_branch == mismatched,
|
||||
"branch patch accepted or changed a different packet type");
|
||||
|
||||
// This stream exceeds native recursion capacity, while chains need one fetcher cursor.
|
||||
std::vector<std::array<uint32_t, 4>> links(65536);
|
||||
std::span<const uint32_t> target = then_commands;
|
||||
|
||||
Reference in New Issue
Block a user