mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
agc: support one-word NOP reservations and share packet sizing
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/file.h"
|
||||
#include "common/hostException.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/subsystems.h"
|
||||
@@ -41778,6 +41779,43 @@ void CheckPm4IndirectControlFlow(RenderContext &renderer) {
|
||||
static_cast<uint32_t>(address(target.data())),
|
||||
static_cast<uint32_t>(address(target.data()) >> 32u), control};
|
||||
};
|
||||
// A one-word NOP must leave the following completion write reachable.
|
||||
std::array<uint32_t, 7> nop_commands{};
|
||||
CommandBufferLayout nop_dcb{nop_commands.data(), nop_commands.data() + nop_commands.size(),
|
||||
nop_commands.data(), nop_commands.data() + nop_commands.size(), nullptr, nullptr, 0};
|
||||
auto* nop_cb = reinterpret_cast<Gen5::CommandBuffer*>(&nop_dcb);
|
||||
Require(name, "zero-sized NOP", Gen5::AgcCbNop(nop_cb, 0) == nullptr &&
|
||||
nop_dcb.cursor_up == nop_commands.data() && nop_commands[0] == 0,
|
||||
"zero-sized reservation changed the command buffer");
|
||||
Require(name, "empty command list NOP", Gen5::AgcCbNop(nop_cb, 1) == nop_commands.data() &&
|
||||
nop_dcb.cursor_up == nop_commands.data() + 1 && nop_commands[0] == 0xffff1000u &&
|
||||
Gen5::AgcCbNopGetSize(1) == 4 && Gen5::AgcGetPacketSize(nop_commands.data()) == 1,
|
||||
"native NOP(1) did not reserve one DWORD");
|
||||
const auto completion = write(&selected, 7);
|
||||
std::copy(completion.begin(), completion.end(), nop_commands.begin() + 1);
|
||||
nop_commands.back() = 0xffff1000u;
|
||||
for (uint32_t predication : {1u, 0u}) {
|
||||
Gen5::AgcSetRangePredication(nop_commands.data(), nop_commands.data() + nop_commands.size(), predication);
|
||||
Require(name, "NOP range predication", nop_commands[0] == (0xffff1000u | predication) &&
|
||||
nop_commands.back() == (0xffff1000u | predication) &&
|
||||
nop_commands[1] == (completion[0] | predication) && nop_commands[5] == 7,
|
||||
"range predication skipped a packet or modified a payload");
|
||||
Pm4Execution execution;
|
||||
selected = 0;
|
||||
Require(name, "NOP and completion execution",
|
||||
processor.Process(execution, nop_commands) == Pm4ProcessResult::Complete && selected == 7,
|
||||
"one-DWORD NOP prevented the completion write or overread the stream end");
|
||||
}
|
||||
Common::File dump;
|
||||
Require(name, "NOP dump file", dump.CreateInMem(), "could not create PM4 dump");
|
||||
Pm4::DumpPm4PacketStream(&dump, nop_commands.data(), 0, nop_commands.size());
|
||||
std::array<uint32_t, 3> payload{0, 0x12345678u, 0x9abcdef0u};
|
||||
CommandBufferLayout payload_dcb{payload.data(), payload.data() + payload.size(),
|
||||
payload.data(), payload.data() + payload.size(), nullptr, nullptr, 0};
|
||||
Require(name, "NOP payload reservation",
|
||||
Gen5::AgcCbNop(reinterpret_cast<Gen5::CommandBuffer*>(&payload_dcb), 3) == payload.data() &&
|
||||
payload == std::array<uint32_t, 3>{0xc0011000u, 0x12345678u, 0x9abcdef0u},
|
||||
"NOP emitter overwrote the caller's reserved payload");
|
||||
const auto then_commands = write(&selected, 11);
|
||||
const auto else_commands = write(&selected, 33);
|
||||
const auto branch_suffix = write(&selected, 44);
|
||||
|
||||
Reference in New Issue
Block a user