From 208c245e959f5341b42fa7df4f72589e2a0ceeb7 Mon Sep 17 00:00:00 2001 From: DH Date: Thu, 17 Oct 2024 01:25:43 +0300 Subject: [PATCH] dce: implement submit and write eop --- rpcsx/gpu/Pipe.cpp | 74 ++++++++++++++++++++++++++++----------------- rpcsx/gpu/Pipe.hpp | 1 + rpcsx/iodev/dce.cpp | 12 +++++--- rpcsx/iodev/dce.hpp | 1 + rpcsx/iodev/gc.cpp | 15 +++++---- 5 files changed, 66 insertions(+), 37 deletions(-) diff --git a/rpcsx/gpu/Pipe.cpp b/rpcsx/gpu/Pipe.cpp index 2023ac3d2..a6c051bc0 100644 --- a/rpcsx/gpu/Pipe.cpp +++ b/rpcsx/gpu/Pipe.cpp @@ -512,6 +512,7 @@ GraphicsPipe::GraphicsPipe(int index) : scheduler(createGfxScheduler(index)) { // IT_SURFACE_SYNC deHandlers[gnm::IT_COND_WRITE] = &GraphicsPipe::condWrite; deHandlers[gnm::IT_EVENT_WRITE] = &GraphicsPipe::eventWrite; + mainHandlers[gnm::IT_EVENT_WRITE_EOP] = &GraphicsPipe::eventWriteEop; deHandlers[gnm::IT_EVENT_WRITE_EOP] = &GraphicsPipe::eventWriteEop; deHandlers[gnm::IT_EVENT_WRITE_EOS] = &GraphicsPipe::eventWriteEos; deHandlers[gnm::IT_RELEASE_MEM] = &GraphicsPipe::releaseMem; @@ -1144,7 +1145,7 @@ bool GraphicsPipe::eventWrite(Ring &ring) { bool GraphicsPipe::eventWriteEop(Ring &ring) { auto eventCntl = ring.rptr[1]; - auto addressLo = ring.rptr[2] & ~3; + auto addressLo = ring.rptr[2]; auto dataCntl = ring.rptr[3]; auto dataLo = ring.rptr[4]; auto dataHi = ring.rptr[5]; @@ -1161,44 +1162,63 @@ bool GraphicsPipe::eventWriteEop(Ring &ring) { context.vgtEventInitiator = eventType; - switch (dataSel) { - case 0: // none - break; - case 1: // 32 bit, low - *reinterpret_cast(pointer) = dataLo; - break; - case 2: // 64 bit - *pointer = dataLo | (static_cast(dataHi) << 32); - break; - case 3: // 64 bit, global GPU clock - *pointer = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - break; - case 4: // 64 bit, perf counter - *pointer = std::chrono::duration_cast( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); - break; + if (pointer != nullptr) { + switch (dataSel) { + case 0: // none + break; + case 1: // 32 bit, low + *reinterpret_cast(pointer) = dataLo; + break; + case 2: // 64 bit + *pointer = dataLo | (static_cast(dataHi) << 32); + break; + case 3: // 64 bit, global GPU clock + *pointer = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + break; + case 4: // 64 bit, perf counter + *pointer = std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + break; - default: - rx::die("unimplemented event write eop data %#x", dataSel); + default: + rx::die("unimplemented event write eop data %#x", dataSel); + } } - if (intSel) { + if (intSel != 0) { orbis::g_context.deviceEventEmitter->emit(orbis::kEvFiltGraphicsCore, 0, kGcEventGfxEop); } - if (intSel == 2) { + std::println("event write eop {}, {}, {}, {:x}, {}, {}, {}:{}", eventIndex, + dataSel, intSel, address, eventType, dataSel, dataHi, dataLo); + + if (intSel != 0 && dataSel == 2) { std::optional request; - int index; + int index = -1; { std::lock_guard lock(eopFlipMtx); - if (eopFlipRequestCount > 0) { - index = --eopFlipRequestCount; + auto data = dataLo | (static_cast(dataHi) << 32); + for (auto &request : std::span(eopFlipRequests, eopFlipRequestCount)) { + if (request.eopValue == data) { + index = &request - eopFlipRequests; + break; + } + } + + if (index >= 0) { request = eopFlipRequests[index]; + + if (index + 1 != eopFlipRequestCount) { + std::swap(eopFlipRequests[index], + eopFlipRequests[eopFlipRequestCount - 1]); + } + + --eopFlipRequestCount; } } diff --git a/rpcsx/gpu/Pipe.hpp b/rpcsx/gpu/Pipe.hpp index 8351c3b75..94da4d1f2 100644 --- a/rpcsx/gpu/Pipe.hpp +++ b/rpcsx/gpu/Pipe.hpp @@ -78,6 +78,7 @@ struct EopFlipRequest { std::uint32_t pid; int bufferIndex; std::uint64_t arg; + std::uint64_t eopValue; }; struct GraphicsPipe { diff --git a/rpcsx/iodev/dce.cpp b/rpcsx/iodev/dce.cpp index 9ca7f7cb4..cbbbbf8ea 100644 --- a/rpcsx/iodev/dce.cpp +++ b/rpcsx/iodev/dce.cpp @@ -396,10 +396,14 @@ static orbis::ErrorCode dce_ioctl(orbis::File *file, std::uint64_t request, gpu.submitFlip(thread->tproc->gfxRing, thread->tproc->pid, args->displayBufferIndex, args->flipArg); } else if (args->eop_nz == 1) { - ORBIS_RET_ON_ERROR( - gpu.submitFlipOnEop(thread->tproc->gfxRing, thread->tproc->pid, - args->displayBufferIndex, args->flipArg)); - *args->eop_val = args->canary; + std::uint64_t eopValue = args->canary; + eopValue ^= 0xff00'0000; + eopValue ^= static_cast(device->eopCount++) << 32; + + ORBIS_RET_ON_ERROR(gpu.submitFlipOnEop( + thread->tproc->gfxRing, thread->tproc->pid, args->displayBufferIndex, + args->flipArg, eopValue)); + *args->eop_val = eopValue; } *args->rout = 0; diff --git a/rpcsx/iodev/dce.hpp b/rpcsx/iodev/dce.hpp index d3cfb81a9..38a6b3d3d 100644 --- a/rpcsx/iodev/dce.hpp +++ b/rpcsx/iodev/dce.hpp @@ -12,6 +12,7 @@ static constexpr auto kVmIdCount = 6; struct DceDevice : IoDevice { orbis::shared_mutex mtx; + std::uint32_t eopCount = 0; std::uint32_t freeVmIds = (1 << (kVmIdCount + 1)) - 1; orbis::uint64_t dmemOffset = ~static_cast(0); diff --git a/rpcsx/iodev/gc.cpp b/rpcsx/iodev/gc.cpp index d898fee40..0d4c6903a 100644 --- a/rpcsx/iodev/gc.cpp +++ b/rpcsx/iodev/gc.cpp @@ -114,13 +114,13 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request, break; } - case 0xc020810c: { // submit and flip? + case 0xc020810c: { // submit and write eop struct Args { - std::uint32_t arg0; - std::uint32_t count; - std::uint32_t *cmds; - std::uint64_t arg3; // flipArg? - std::uint32_t arg4; // bufferIndex? + orbis::uint32_t arg0; + orbis::uint32_t count; + orbis::ptr cmds; + orbis::uint64_t eopValue; + orbis::uint32_t waitFlag; }; auto args = reinterpret_cast(argp); @@ -131,6 +131,9 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request, orbis::g_currentThread->tproc->vmId, {args->cmds + i * 4, 4}); } + + // ORBIS_LOG_ERROR("submit and write eop", args->eopValue, args->waitFlag); + gpu.submitWriteEop(gcFile->gfxPipe, args->waitFlag, args->eopValue); } else { return orbis::ErrorCode::BUSY; }