diff --git a/rpcsx/gpu/Pipe.cpp b/rpcsx/gpu/Pipe.cpp index fdf5b2f1d..5ffd790fa 100644 --- a/rpcsx/gpu/Pipe.cpp +++ b/rpcsx/gpu/Pipe.cpp @@ -95,6 +95,7 @@ ComputePipe::ComputePipe(int index) commandHandlers[gnm::IT_RELEASE_MEM] = &ComputePipe::releaseMem; commandHandlers[gnm::IT_WAIT_REG_MEM] = &ComputePipe::waitRegMem; commandHandlers[gnm::IT_WRITE_DATA] = &ComputePipe::writeData; + commandHandlers[gnm::IT_INDIRECT_BUFFER] = &ComputePipe::indirectBuffer; } bool ComputePipe::processAllRings() { @@ -104,6 +105,7 @@ bool ComputePipe::processAllRings() { std::lock_guard lock(queueMtx[&queue - queues]); for (auto &ring : queue) { + currentQueueId = &ring - queue; if (!processRing(ring)) { allProcessed = false; } @@ -172,6 +174,19 @@ bool ComputePipe::processRing(Ring &ring) { return true; } +void ComputePipe::setIndirectRing(int queueId, int indirectLevel, Ring ring) { + if (indirectLevel != 1) { + rx::die("unexpected compute indirect ring indirect level %d", + ring.indirectLevel); + } + + ring.indirectLevel = indirectLevel; + std::println("mapQueue: {}, {}, {}", (void *)ring.base, (void *)ring.wptr, + ring.size); + + queues[1 - ring.indirectLevel][queueId] = ring; +} + void ComputePipe::mapQueue(int queueId, Ring ring, std::unique_lock &lock) { if (ring.indirectLevel < 0 || ring.indirectLevel > 1) { @@ -390,6 +405,24 @@ bool ComputePipe::writeData(Ring &ring) { return true; } +bool ComputePipe::indirectBuffer(Ring &ring) { + rx::dieIf(ring.indirectLevel < 0, "unexpected indirect buffer from CP"); + + auto addressLo = ring.rptr[1] & ~3; + auto addressHi = ring.rptr[2] & ((1 << 8) - 1); + int vmId = ring.rptr[3] >> 24; + auto ibSize = ring.rptr[3] & ((1 << 20) - 1); + auto address = addressLo | (static_cast(addressHi) << 32); + + if (ring.indirectLevel != 0) { + vmId = ring.vmId; + } + auto rptr = RemoteMemory{vmId}.getPointer(address); + setIndirectRing(currentQueueId, ring.indirectLevel + 1, + Ring::createFromRange(vmId, rptr, ibSize)); + return true; +} + bool ComputePipe::unknownPacket(Ring &ring) { auto op = rx::getBits(ring.rptr[0], 15, 8); diff --git a/rpcsx/gpu/Pipe.hpp b/rpcsx/gpu/Pipe.hpp index 18ab4ecdb..c4b07bc6c 100644 --- a/rpcsx/gpu/Pipe.hpp +++ b/rpcsx/gpu/Pipe.hpp @@ -42,6 +42,7 @@ struct ComputePipe { CommandHandler commandHandlers[255]; orbis::shared_mutex queueMtx[8]; int index; + int currentQueueId; Ring queues[2][8]; std::uint64_t drawIndexIndirPatchBase = 0; @@ -49,6 +50,7 @@ struct ComputePipe { bool processAllRings(); bool processRing(Ring &ring); + void setIndirectRing(int queueId, int level, Ring ring); void mapQueue(int queueId, Ring ring, std::unique_lock &lock); void waitForIdle(int queueId, std::unique_lock &lock); void submit(int queueId, std::uint32_t offset); @@ -63,6 +65,7 @@ struct ComputePipe { bool releaseMem(Ring &ring); bool waitRegMem(Ring &ring); bool writeData(Ring &ring); + bool indirectBuffer(Ring &ring); bool unknownPacket(Ring &ring); bool handleNop(Ring &ring);