Split syncpoints into host-guest pairs

This allows for the presentation engine to grab the presentation image early when direct buffers are in use, since it'll handle sync on its own using semaphores it doesn't need to wait for GPU execution.
This commit is contained in:
Billy Laws 2022-12-27 19:12:13 +00:00
parent 966c31810a
commit 90e21b0ca1
7 changed files with 24 additions and 9 deletions
app/src/main/cpp/skyline
services
hosbinder
nvdrv
soc

@ -64,7 +64,7 @@ namespace skyline::service::hosbinder {
throw exception("Wait has larger fence count ({}) than storage size ({})", fenceCount, fences.size()); throw exception("Wait has larger fence count ({}) than storage size ({})", fenceCount, fences.size());
for (auto it{fences.begin()}, end{fences.begin() + fenceCount}; it < end; it++) for (auto it{fences.begin()}, end{fences.begin() + fenceCount}; it < end; it++)
if (it->id != InvalidFenceId) if (it->id != InvalidFenceId)
host1x.syncpoints.at(it->id).Wait(it->threshold, std::chrono::steady_clock::duration::max()); host1x.syncpoints.at(it->id).host.Wait(it->threshold, std::chrono::steady_clock::duration::max());
} }
}; };

@ -79,7 +79,7 @@ namespace skyline::service::nvdrv::core {
if (!syncpoints.at(id).reserved) if (!syncpoints.at(id).reserved)
throw exception("Cannot update an unreserved syncpoint!"); throw exception("Cannot update an unreserved syncpoint!");
syncpoints.at(id).counterMin = state.soc->host1x.syncpoints.at(id).Load(); syncpoints.at(id).counterMin = state.soc->host1x.syncpoints.at(id).host.Load();
return syncpoints.at(id).counterMin; return syncpoints.at(id).counterMin;
} }

@ -18,14 +18,14 @@ namespace skyline::service::nvdrv::device::nvhost {
} }
void Ctrl::SyncpointEvent::Cancel(soc::host1x::Host1x &host1x) { void Ctrl::SyncpointEvent::Cancel(soc::host1x::Host1x &host1x) {
host1x.syncpoints.at(fence.id).DeregisterWaiter(waiterHandle); host1x.syncpoints.at(fence.id).host.DeregisterWaiter(waiterHandle);
waiterHandle = {}; waiterHandle = {};
} }
void Ctrl::SyncpointEvent::RegisterWaiter(soc::host1x::Host1x &host1x, const Fence &pFence) { void Ctrl::SyncpointEvent::RegisterWaiter(soc::host1x::Host1x &host1x, const Fence &pFence) {
fence = pFence; fence = pFence;
state = State::Waiting; state = State::Waiting;
waiterHandle = host1x.syncpoints.at(fence.id).RegisterWaiter(fence.threshold, [this] { Signal(); }); waiterHandle = host1x.syncpoints.at(fence.id).host.RegisterWaiter(fence.threshold, [this] { Signal(); });
} }
bool Ctrl::SyncpointEvent::IsInUse() { bool Ctrl::SyncpointEvent::IsInUse() {

@ -20,8 +20,9 @@ namespace skyline::soc::gm20b::engine {
if (action.operation == Registers::Syncpoint::Operation::Incr) { if (action.operation == Registers::Syncpoint::Operation::Incr) {
Logger::Debug("Increment syncpoint: {}", +action.index); Logger::Debug("Increment syncpoint: {}", +action.index);
channelCtx.executor.Submit([=, syncpoints = &this->syncpoints, index = action.index]() { channelCtx.executor.Submit([=, syncpoints = &this->syncpoints, index = action.index]() {
syncpoints->at(index).Increment(); syncpoints->at(index).host.Increment();
}); });
syncpoints.at(action.index).guest.Increment();
} else if (action.operation == Registers::Syncpoint::Operation::Wait) { } else if (action.operation == Registers::Syncpoint::Operation::Wait) {
Logger::Debug("Wait syncpoint: {}, thresh: {}", +action.index, registers.syncpoint->payload); Logger::Debug("Wait syncpoint: {}, thresh: {}", +action.index, registers.syncpoint->payload);
@ -29,7 +30,7 @@ namespace skyline::soc::gm20b::engine {
channelCtx.executor.Submit(); channelCtx.executor.Submit();
channelCtx.Unlock(); channelCtx.Unlock();
syncpoints.at(action.index).Wait(registers.syncpoint->payload, std::chrono::steady_clock::duration::max()); syncpoints.at(action.index).host.Wait(registers.syncpoint->payload, std::chrono::steady_clock::duration::max());
channelCtx.Lock(); channelCtx.Lock();
} }
}) })

@ -219,8 +219,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
ENGINE_CASE(syncpointAction, { ENGINE_CASE(syncpointAction, {
Logger::Debug("Increment syncpoint: {}", static_cast<u16>(syncpointAction.id)); Logger::Debug("Increment syncpoint: {}", static_cast<u16>(syncpointAction.id));
channelCtx.executor.Submit([=, syncpoints = &this->syncpoints, index = syncpointAction.id]() { channelCtx.executor.Submit([=, syncpoints = &this->syncpoints, index = syncpointAction.id]() {
syncpoints->at(index).Increment(); syncpoints->at(index).host.Increment();
}); });
syncpoints.at(syncpointAction.id).guest.Increment();
}) })
ENGINE_CASE(clearSurface, { ENGINE_CASE(clearSurface, {

@ -30,7 +30,7 @@ namespace skyline::soc::host1x {
u32 syncpointId{static_cast<u8>(argument)}; u32 syncpointId{static_cast<u8>(argument)};
Logger::Debug("Wait syncpoint: {}, thresh: {}", syncpointId, syncpointPayload); Logger::Debug("Wait syncpoint: {}, thresh: {}", syncpointId, syncpointPayload);
syncpoints.at(syncpointId).Wait(syncpointPayload, std::chrono::steady_clock::duration::max()); syncpoints.at(syncpointId).host.Wait(syncpointPayload, std::chrono::steady_clock::duration::max());
break; break;
} }

@ -62,5 +62,18 @@ namespace skyline::soc::host1x {
bool Wait(u32 threshold, std::chrono::steady_clock::duration timeout); bool Wait(u32 threshold, std::chrono::steady_clock::duration timeout);
}; };
using SyncpointSet = std::array<Syncpoint, SyncpointCount>; /**
* @bried Holds host and guest copies of an individual syncpoint
*/
struct SyncpointPair {
Syncpoint guest; //!< Incremented at GPFIFO processing time
Syncpoint host; //!< Incremented after host GPU completion
void Increment() {
guest.Increment();
host.Increment();
}
};
using SyncpointSet = std::array<SyncpointPair, SyncpointCount>;
} }