dce: implement submit and write eop

This commit is contained in:
DH 2024-10-17 01:25:43 +03:00
parent bdd4b91a32
commit 208c245e95
5 changed files with 66 additions and 37 deletions

View file

@ -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<std::uint32_t *>(pointer) = dataLo;
break;
case 2: // 64 bit
*pointer = dataLo | (static_cast<std::uint64_t>(dataHi) << 32);
break;
case 3: // 64 bit, global GPU clock
*pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
break;
case 4: // 64 bit, perf counter
*pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
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<std::uint32_t *>(pointer) = dataLo;
break;
case 2: // 64 bit
*pointer = dataLo | (static_cast<std::uint64_t>(dataHi) << 32);
break;
case 3: // 64 bit, global GPU clock
*pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
break;
case 4: // 64 bit, perf counter
*pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
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<EopFlipRequest> request;
int index;
int index = -1;
{
std::lock_guard lock(eopFlipMtx);
if (eopFlipRequestCount > 0) {
index = --eopFlipRequestCount;
auto data = dataLo | (static_cast<std::uint64_t>(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;
}
}

View file

@ -78,6 +78,7 @@ struct EopFlipRequest {
std::uint32_t pid;
int bufferIndex;
std::uint64_t arg;
std::uint64_t eopValue;
};
struct GraphicsPipe {

View file

@ -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<std::uint64_t>(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;

View file

@ -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<std::uint64_t>(0);

View file

@ -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<orbis::uint32_t> cmds;
orbis::uint64_t eopValue;
orbis::uint32_t waitFlag;
};
auto args = reinterpret_cast<Args *>(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;
}