graphics: execute valid PM4 rewind packets

This commit is contained in:
nmzik
2026-08-16 21:55:38 +02:00
parent e1366eb91d
commit 6b306f64d5
6 changed files with 59 additions and 0 deletions
@@ -112,6 +112,7 @@ public:
void SetCeComplete(bool complete) { m_ce_complete = complete; } void SetCeComplete(bool complete) { m_ce_complete = complete; }
void WaitCe(); void WaitCe();
void WaitDeDiff(uint32_t diff); void WaitDeDiff(uint32_t diff);
void WaitForRewind(bool valid);
void IncrementDe(); void IncrementDe();
void IncrementCe(); void IncrementCe();
@@ -224,6 +224,7 @@ constexpr auto MakeOpcodeDispatchTable() {
g_cp_op_func[Pm4::IT_EVENT_WRITE_EOS] = CpOpEventWriteEos; g_cp_op_func[Pm4::IT_EVENT_WRITE_EOS] = CpOpEventWriteEos;
g_cp_op_func[Pm4::IT_DMA_DATA] = CpOpDmaData; g_cp_op_func[Pm4::IT_DMA_DATA] = CpOpDmaData;
g_cp_op_func[Pm4::IT_ACQUIRE_MEM] = CpOpAcquireMem; g_cp_op_func[Pm4::IT_ACQUIRE_MEM] = CpOpAcquireMem;
g_cp_op_func[Pm4::IT_REWIND] = CpOpRewind;
g_cp_op_func[Pm4::IT_SET_CONTEXT_REG] = CpOpSetContextReg; g_cp_op_func[Pm4::IT_SET_CONTEXT_REG] = CpOpSetContextReg;
g_cp_op_func[Pm4::IT_SET_SH_REG] = CpOpSetShaderReg; g_cp_op_func[Pm4::IT_SET_SH_REG] = CpOpSetShaderReg;
g_cp_op_func[Pm4::IT_SET_UCONFIG_REG] = CpOpSetUconfigReg; g_cp_op_func[Pm4::IT_SET_UCONFIG_REG] = CpOpSetUconfigReg;
@@ -133,6 +133,7 @@ uint32_t CpOpDrawIndirectMulti(CommandProcessor&, uint32_t, const uint32_t*, uin
uint32_t CpOpDrawIndex(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpDrawIndex(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpDrawIndexOffset(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpDrawIndexOffset(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpPfpSyncMe(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpPfpSyncMe(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpRewind(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpIndexType(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpIndexType(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpNumInstances(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpNumInstances(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
uint32_t CpOpDrawIndexAuto(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t); uint32_t CpOpDrawIndexAuto(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
@@ -1830,6 +1830,17 @@ KYTY_CP_OP_PARSER(CpOpPfpSyncMe) {
return 1; return 1;
} }
KYTY_CP_OP_PARSER(CpOpRewind) {
KYTY_PROFILER_FUNCTION();
EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0005900);
EXIT_NOT_IMPLEMENTED((buffer[0] & ~0x81000000u) != 0);
cp.WaitForRewind((buffer[0] & 0x80000000u) != 0);
return 1;
}
KYTY_CP_OP_PARSER(CpOpSetPredication) { KYTY_CP_OP_PARSER(CpOpSetPredication) {
KYTY_PROFILER_FUNCTION(); KYTY_PROFILER_FUNCTION();
+6
View File
@@ -374,6 +374,12 @@ void CommandProcessor::WaitDeDiff(uint32_t diff) {
} }
} }
void CommandProcessor::WaitForRewind(bool valid) {
if (!valid) {
SuspendPm4();
}
}
void CommandProcessor::IncrementDe() { void CommandProcessor::IncrementDe() {
m_de_count++; m_de_count++;
} }
+39
View File
@@ -21096,6 +21096,39 @@ void CheckPm4WaitResume(RenderContext &renderer) {
std::printf("[host] %-32s ok\n", "Pm4WaitResume"); std::printf("[host] %-32s ok\n", "Pm4WaitResume");
} }
void CheckPm4RewindResume(RenderContext &renderer) {
GraphicsInitJmpTables();
CommandProcessor processor(renderer);
uint32_t suffix = 0;
const auto address = reinterpret_cast<uint64_t>(&suffix);
std::array<uint32_t, 7> commands{};
commands[0] = KYTY_PM4(2, Pm4::IT_REWIND, 0);
commands[1] = 0;
commands[2] = KYTY_PM4(5, Pm4::IT_WRITE_DATA, 0);
commands[3] = 0;
commands[4] = static_cast<uint32_t>(address);
commands[5] = static_cast<uint32_t>(address >> 32u);
commands[6] = 33;
Pm4Execution execution;
Require("Pm4RewindResume", "pending",
processor.Process(execution, commands.data(), commands.size()) ==
Pm4ProcessResult::Blocked &&
suffix == 0,
"pending rewind did not preserve its command position");
Require("Pm4RewindResume", "patch valid",
Gen5::AgcRewindPatchSetRewindState(commands.data(), 1) == 0 &&
commands[1] == 0x80000000u,
"rewind state patch did not set the valid bit");
Require("Pm4RewindResume", "resume",
processor.Process(execution, commands.data(), commands.size()) ==
Pm4ProcessResult::Complete &&
suffix == 33,
"valid rewind did not resume at the following packet");
std::printf("[host] %-32s ok\n", "Pm4RewindResume");
}
void CheckPm4CeCompletion(RenderContext &renderer) { void CheckPm4CeCompletion(RenderContext &renderer) {
GraphicsInitJmpTables(); GraphicsInitJmpTables();
CommandProcessor processor(renderer); CommandProcessor processor(renderer);
@@ -21223,6 +21256,11 @@ int main(int argc, char **argv) {
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer()); CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
return 0; return 0;
} }
if (argc == 2 && std::strcmp(argv[1], "--rewind-only") == 0) {
VulkanHarness vulkan;
CheckPm4RewindResume(vulkan.RuntimeRenderer());
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--image-overlap-only") == 0) { if (argc == 2 && std::strcmp(argv[1], "--image-overlap-only") == 0) {
CheckDepthAttachmentWrites(); CheckDepthAttachmentWrites();
CheckDynamicRenderingState(); CheckDynamicRenderingState();
@@ -21381,6 +21419,7 @@ int main(int argc, char **argv) {
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer()); CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer()); CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
CheckPm4WaitResume(vulkan.RuntimeRenderer()); CheckPm4WaitResume(vulkan.RuntimeRenderer());
CheckPm4RewindResume(vulkan.RuntimeRenderer());
CheckPm4CeCompletion(vulkan.RuntimeRenderer()); CheckPm4CeCompletion(vulkan.RuntimeRenderer());
CheckEmbeddedFetchVertexOffset(); CheckEmbeddedFetchVertexOffset();
CheckEmbeddedFetchLaneSpill(); CheckEmbeddedFetchLaneSpill();