Bug 1845697 - Always enable IPC congestion check in WebGLChild::FlushPendingCmds() r=jgilbert,gfx-reviewers,lsalzman

IPC congestion check was added by Bug 1839314. It is enabled only when async remote texture is enabled and after first ClientWebGLContext::GetFrontBuffer() call. There were cases that it does not work like the followings.
- ClientWebGLContext::GetFrontBuffer() was not called during IPC congestion.
- When gfx::gfxVars::WebglOopAsyncPresentForceSync() = true.

When the IPC congestion happened, it caused ouf of file descriptor on Linux. Then it is better always to enable the IPC congestion check in WebGLChild::FlushPendingCmds().

Differential Revision: https://phabricator.services.mozilla.com/D184917
This commit is contained in:
sotaro
2023-08-01 00:18:12 +00:00
parent e838a5923e
commit 31ad5bf633
3 changed files with 54 additions and 57 deletions

View File

@@ -535,28 +535,18 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
child->FlushPendingCmds(); child->FlushPendingCmds();
Maybe<layers::SurfaceDescriptor> ret; Maybe<layers::SurfaceDescriptor> ret;
auto& info = child->GetFlushedCmdInfo();
// If valid remote texture data was set for async present, then use it. // If valid remote texture data was set for async present, then use it.
const auto& ownerId = fb ? fb->mRemoteTextureOwnerId : mRemoteTextureOwnerId; const auto& ownerId = fb ? fb->mRemoteTextureOwnerId : mRemoteTextureOwnerId;
const auto& textureId = fb ? fb->mLastRemoteTextureId : mLastRemoteTextureId; const auto& textureId = fb ? fb->mLastRemoteTextureId : mLastRemoteTextureId;
auto& needsSync = fb ? fb->mNeedsRemoteTextureSync : mNeedsRemoteTextureSync; auto& needsSync = fb ? fb->mNeedsRemoteTextureSync : mNeedsRemoteTextureSync;
if (ownerId && textureId) { if (ownerId && textureId) {
auto& info = child->GetFlushedCmdInfo();
if (!gfx::gfxVars::WebglOopAsyncPresentForceSync() &&
info.flushesSinceLastCongestionCheck.isNothing()) {
// Enabling checking of increase of flush cmds.
info.flushesSinceLastCongestionCheck = Some(0);
}
const auto tooManyFlushes = 10; const auto tooManyFlushes = 10;
if (info.flushesSinceLastCongestionCheck.isSome()) { // If there are many flushed cmds, force synchronous IPC to avoid too many
// If there are many flushed cmds, force synchronous IPC to avoid too many // pending ipc messages.
// pending ipc messages. if (info.flushesSinceLastCongestionCheck > tooManyFlushes) {
if (info.flushesSinceLastCongestionCheck.ref() > tooManyFlushes) { needsSync = true;
needsSync = true;
}
// Reset flushesSinceLastCongestionCheck
info.flushesSinceLastCongestionCheck = Some(0);
info.congestionCheckGeneration++;
} }
if (XRE_IsParentProcess() || if (XRE_IsParentProcess() ||
gfx::gfxVars::WebglOopAsyncPresentForceSync() || needsSync) { gfx::gfxVars::WebglOopAsyncPresentForceSync() || needsSync) {
@@ -565,11 +555,19 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
// will continue to use the remote texture descriptor after. // will continue to use the remote texture descriptor after.
(void)child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret); (void)child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret);
} }
// Reset flushesSinceLastCongestionCheck
info.flushesSinceLastCongestionCheck = 0;
info.congestionCheckGeneration++;
return Some(layers::SurfaceDescriptorRemoteTexture(*textureId, *ownerId)); return Some(layers::SurfaceDescriptorRemoteTexture(*textureId, *ownerId));
} }
if (!child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret)) return {}; if (!child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret)) return {};
// Reset flushesSinceLastCongestionCheck
info.flushesSinceLastCongestionCheck = 0;
info.congestionCheckGeneration++;
return ret; return ret;
} }

View File

@@ -74,47 +74,46 @@ void WebGLChild::FlushPendingCmds() {
mFlushedCmdInfo.flushes += 1; mFlushedCmdInfo.flushes += 1;
mFlushedCmdInfo.flushedCmdBytes += byteSize; mFlushedCmdInfo.flushedCmdBytes += byteSize;
mFlushedCmdInfo.overhead += mPendingCmdsAlignmentOverhead; mFlushedCmdInfo.overhead += mPendingCmdsAlignmentOverhead;
if (mFlushedCmdInfo.flushesSinceLastCongestionCheck.isSome()) {
mFlushedCmdInfo.flushesSinceLastCongestionCheck.ref() += 1;
const auto startCongestionCheck = 20;
const auto maybeIPCMessageCongestion = 70;
const auto eventTarget = GetCurrentSerialEventTarget();
MOZ_ASSERT(eventTarget);
RefPtr<WebGLChild> self = this;
size_t generation = self->mFlushedCmdInfo.congestionCheckGeneration;
// When ClientWebGLContext uses async remote texture, sync GetFrontBuffer // Handle flushesSinceLastCongestionCheck
// message is not sent in ClientWebGLContext::GetFrontBuffer(). It causes a mFlushedCmdInfo.flushesSinceLastCongestionCheck += 1;
// case that a lot of async DispatchCommands messages are sent to const auto startCongestionCheck = 20;
// WebGLParent without calling ClientWebGLContext::GetFrontBuffer(). The const auto maybeIPCMessageCongestion = 70;
// sending DispatchCommands messages could be faster than receiving message const auto eventTarget = GetCurrentSerialEventTarget();
// at WebGLParent by WebGLParent::RecvDispatchCommands(). If it happens, MOZ_ASSERT(eventTarget);
// pending IPC messages could grow too much until out of resource. To detect RefPtr<WebGLChild> self = this;
// the messages congestion, async Ping message is used. If the Ping response size_t generation = self->mFlushedCmdInfo.congestionCheckGeneration;
// is not received until maybeIPCMessageCongestion, IPC message might be
// congested at WebGLParent. Then sending sync SyncPing flushes all pending // When ClientWebGLContext uses async remote texture, sync GetFrontBuffer
// messages. // message is not sent in ClientWebGLContext::GetFrontBuffer(). It causes a
// Due to the async nature of the async ping, it is possible for the flush // case that a lot of async DispatchCommands messages are sent to
// check to exceed maybeIPCMessageCongestion, but that it it still bounded. // WebGLParent without calling ClientWebGLContext::GetFrontBuffer(). The
if (mFlushedCmdInfo.flushesSinceLastCongestionCheck.ref() == // sending DispatchCommands messages could be faster than receiving message
startCongestionCheck) { // at WebGLParent by WebGLParent::RecvDispatchCommands(). If it happens,
SendPing()->Then(eventTarget, __func__, [self, generation]() { // pending IPC messages could grow too much until out of resource. To detect
if (generation == self->mFlushedCmdInfo.congestionCheckGeneration) { // the messages congestion, async Ping message is used. If the Ping response
// Confirmed IPC messages congestion does not happen. // is not received until maybeIPCMessageCongestion, IPC message might be
// Reset flushesSinceLastCongestionCheck for next congestion check. // congested at WebGLParent. Then sending sync SyncPing flushes all pending
self->mFlushedCmdInfo.flushesSinceLastCongestionCheck = Some(0); // messages.
self->mFlushedCmdInfo.congestionCheckGeneration++; // Due to the async nature of the async ping, it is possible for the flush
} // check to exceed maybeIPCMessageCongestion, but that it it still bounded.
}); if (mFlushedCmdInfo.flushesSinceLastCongestionCheck == startCongestionCheck) {
} else if (mFlushedCmdInfo.flushesSinceLastCongestionCheck.ref() > SendPing()->Then(eventTarget, __func__, [self, generation]() {
maybeIPCMessageCongestion) { if (generation == self->mFlushedCmdInfo.congestionCheckGeneration) {
// IPC messages congestion might happen, send sync SyncPing for flushing // Confirmed IPC messages congestion does not happen.
// pending messages. // Reset flushesSinceLastCongestionCheck for next congestion check.
SendSyncPing(); self->mFlushedCmdInfo.flushesSinceLastCongestionCheck = 0;
// Reset flushesSinceLastCongestionCheck for next congestion check. self->mFlushedCmdInfo.congestionCheckGeneration++;
mFlushedCmdInfo.flushesSinceLastCongestionCheck = Some(0); }
mFlushedCmdInfo.congestionCheckGeneration++; });
} } else if (mFlushedCmdInfo.flushesSinceLastCongestionCheck >
maybeIPCMessageCongestion) {
// IPC messages congestion might happen, send sync SyncPing for flushing
// pending messages.
SendSyncPing();
// Reset flushesSinceLastCongestionCheck for next congestion check.
mFlushedCmdInfo.flushesSinceLastCongestionCheck = 0;
mFlushedCmdInfo.congestionCheckGeneration++;
} }
if (gl::GLContext::ShouldSpew()) { if (gl::GLContext::ShouldSpew()) {

View File

@@ -22,8 +22,8 @@ namespace dom {
struct FlushedCmdInfo final { struct FlushedCmdInfo final {
size_t flushes = 0; size_t flushes = 0;
// Store a number of flushes since last IPC congestion check. // Store a number of flushes since last IPC congestion check.
// It is reset to Some(0), when current IPC congestion check is done. // It is reset to 0, when current IPC congestion check is done.
Maybe<size_t> flushesSinceLastCongestionCheck; size_t flushesSinceLastCongestionCheck = 0;
// Incremented for each IPC congestion check. // Incremented for each IPC congestion check.
size_t congestionCheckGeneration = 0; size_t congestionCheckGeneration = 0;
size_t flushedCmdBytes = 0; size_t flushedCmdBytes = 0;