diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index a4eae8e7..8db2d63c 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -610,6 +610,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); break; } + case PM4ItOpcode::Rewind: { + const PM4CmdRewind* rewind = reinterpret_cast(header); + while (!rewind->Valid()) { + mapped_queues[GfxQueueId].cs_state = regs.cs_program; + TracyFiberLeave; + co_yield {}; + TracyFiberEnter(dcb_task_name); + regs.cs_program = mapped_queues[GfxQueueId].cs_state; + } + break; + } case PM4ItOpcode::WaitRegMem: { const auto* wait_reg_mem = reinterpret_cast(header); // ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me); @@ -630,6 +641,19 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); + auto task = ProcessGraphics( + {indirect_buffer->Address(), indirect_buffer->ib_size}, {}); + while (!task.handle.done()) { + task.handle.resume(); + + TracyFiberLeave; + co_yield {}; + TracyFiberEnter(dcb_task_name); + }; + break; + } case PM4ItOpcode::IncrementDeCounter: { ++cblock.de_count; break; @@ -730,6 +754,17 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { case PM4ItOpcode::AcquireMem: { break; } + case PM4ItOpcode::Rewind: { + const PM4CmdRewind* rewind = reinterpret_cast(header); + while (!rewind->Valid()) { + mapped_queues[vqid].cs_state = regs.cs_program; + TracyFiberLeave; + co_yield {}; + TracyFiberEnter(acb_task_name); + regs.cs_program = mapped_queues[vqid].cs_state; + } + break; + } case PM4ItOpcode::SetShReg: { const auto* set_data = reinterpret_cast(header); std::memcpy(®s.reg_array[ShRegWordOffset + set_data->reg_offset], header + 2, diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index be675128..238e09fa 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -418,6 +418,19 @@ struct PM4DmaData { } }; +struct PM4CmdRewind { + PM4Type3Header header; + union { + u32 raw; + BitField<24, 1, u32> offload_enable; ///< Enable offload polling valid bit to IQ + BitField<31, 1, u32> valid; ///< Set when subsequent packets are valid + }; + + bool Valid() const { + return valid; + } +}; + struct PM4CmdWaitRegMem { enum class Engine : u32 { Me = 0u, Pfp = 1u }; enum class MemSpace : u32 { Register = 0u, Memory = 1u };