mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
[Perf] (MG_Remote): the apply loop hands its poll's ring head to the drain, so a woken drain does not poll the GPU-fault verdict twice (Espryt rd12 inproc apply thread 1.34 -> 0.78 ms/frame).
This commit is contained in:
@@ -708,8 +708,14 @@ namespace MobileGL::MG_Remote::Server {
|
|||||||
// backend's verdict - the driver's GUILTY report on Espryt, the hang watch on Magma - is
|
// backend's verdict - the driver's GUILTY report on Espryt, the hang watch on Magma - is
|
||||||
// asked HERE, before the drain, so that frame is never applied: the session latches
|
// asked HERE, before the drain, so that frame is never applied: the session latches
|
||||||
// (DeviceLost, its client reads a lost context) and leaves below. Cheap by contract.
|
// (DeviceLost, its client reads a lost context) and leaves below. Cheap by contract.
|
||||||
if (m_backend != nullptr && !SessionLatched()) (void)m_backend->LatchIfGpuFaulted();
|
// The head is loaded BEFORE the poll, so every record below it was in the ring when the
|
||||||
if (eventRingHasRoom()) DrainRing();
|
// poll ran and the drain need not poll for it again (DrainRing's `polledHead`).
|
||||||
|
std::uint64_t polledHead = 0;
|
||||||
|
if (m_backend != nullptr && !SessionLatched()) {
|
||||||
|
polledHead = signals.CmdHead != nullptr ? signals.CmdHead->load(std::memory_order_acquire) : 0;
|
||||||
|
(void)m_backend->LatchIfGpuFaulted();
|
||||||
|
}
|
||||||
|
if (eventRingHasRoom()) DrainRing(polledHead);
|
||||||
if (stopOrForfeit()) break;
|
if (stopOrForfeit()) break;
|
||||||
// The session-targeted device-loss debug knob (PipeSessionFail.h): asked here, after a
|
// The session-targeted device-loss debug knob (PipeSessionFail.h): asked here, after a
|
||||||
// drain, so it reaches a client that never presents or reads back, once the session
|
// drain, so it reaches a client that never presents or reads back, once the session
|
||||||
@@ -1013,7 +1019,7 @@ namespace MobileGL::MG_Remote::Server {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint64 ServerLoop::DrainRing() {
|
Uint64 ServerLoop::DrainRing(std::uint64_t polledHead) {
|
||||||
// THE EMPTY-RING ANSWER COSTS TWO LOADS AND NOTHING ELSE, and that was AUDITED rather
|
// THE EMPTY-RING ANSWER COSTS TWO LOADS AND NOTHING ELSE, and that was AUDITED rather
|
||||||
// than assumed (P5d round 3, package T item 2): the idle poll calls this on every
|
// than assumed (P5d round 3, package T item 2): the idle poll calls this on every
|
||||||
// iteration, so a lock or a clock read in here would be the same defect
|
// iteration, so a lock or a clock read in here would be the same defect
|
||||||
@@ -1101,12 +1107,11 @@ namespace MobileGL::MG_Remote::Server {
|
|||||||
// previous record was applied and acknowledged, so after a reset the driver may already
|
// previous record was applied and acknowledged, so after a reset the driver may already
|
||||||
// report - used to be popped and applied unpolled, and a GUILTY context ran one more record
|
// report - used to be popped and applied unpolled, and a GUILTY context ran one more record
|
||||||
// (ServerLoopEglLatchTest under CPU load). `polledHead` is the command ring's head as loaded
|
// (ServerLoopEglLatchTest under CPU load). `polledHead` is the command ring's head as loaded
|
||||||
// just BEFORE the last poll: every record below it was visible when that poll ran. A record
|
// just BEFORE the last poll (the apply loop's own, handed in): every record below it was
|
||||||
// at or past it re-loads the head and polls first. While the client stays ahead this is one
|
// visible when that poll ran. A record at or past it re-loads the head and polls first. While the client stays ahead this is one
|
||||||
// poll per batch the drain catches up to, never more than one per record.
|
// poll per batch the drain catches up to, never more than one per record.
|
||||||
Transport::LinkSignals signals{};
|
Transport::LinkSignals signals{};
|
||||||
if (auto* link = session.DataLink()) signals = link->Signals();
|
if (auto* link = session.DataLink()) signals = link->Signals();
|
||||||
std::uint64_t polledHead = 0;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (SessionLatched()) break;
|
if (SessionLatched()) break;
|
||||||
if (m_windowRequests.load(std::memory_order_acquire) != 0) {
|
if (m_windowRequests.load(std::memory_order_acquire) != 0) {
|
||||||
|
|||||||
@@ -548,7 +548,9 @@ namespace MobileGL::MG_Remote::Server {
|
|||||||
// the probe's metadata is protected for the same lifetime as its frame.
|
// the probe's metadata is protected for the same lifetime as its frame.
|
||||||
MobileGLResult PostSurfaceControlFrameWithCallerLock(SurfaceControlFrame& frame);
|
MobileGLResult PostSurfaceControlFrameWithCallerLock(SurfaceControlFrame& frame);
|
||||||
// Pops and applies every record currently in the ring; returns how many it applied.
|
// Pops and applies every record currently in the ring; returns how many it applied.
|
||||||
Uint64 DrainRing();
|
// `polledHead`: the command ring's head as loaded just before the caller's own fault poll
|
||||||
|
// (0 when the caller did not poll) - records below it need no poll of their own.
|
||||||
|
Uint64 DrainRing(std::uint64_t polledHead = 0);
|
||||||
void SignalExited();
|
void SignalExited();
|
||||||
|
|
||||||
ServerSession* m_session = nullptr;
|
ServerSession* m_session = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user