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

View File

@ -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());
} }
}; };

View File

@ -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;
} }

View File

@ -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() {

View File

@ -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();
} }
}) })

View File

@ -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, {

View File

@ -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;
} }

View File

@ -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>;
} }