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
Родитель db4ed173eb
Коммит 7998255fe4
3 изменённых файлов: 54 добавлений и 57 удалений

Просмотреть файл

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

Просмотреть файл

@ -74,47 +74,46 @@ void WebGLChild::FlushPendingCmds() {
mFlushedCmdInfo.flushes += 1;
mFlushedCmdInfo.flushedCmdBytes += byteSize;
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
// message is not sent in ClientWebGLContext::GetFrontBuffer(). It causes a
// case that a lot of async DispatchCommands messages are sent to
// WebGLParent without calling ClientWebGLContext::GetFrontBuffer(). The
// sending DispatchCommands messages could be faster than receiving message
// at WebGLParent by WebGLParent::RecvDispatchCommands(). If it happens,
// pending IPC messages could grow too much until out of resource. To detect
// the messages congestion, async Ping message is used. If the Ping response
// is not received until maybeIPCMessageCongestion, IPC message might be
// congested at WebGLParent. Then sending sync SyncPing flushes all pending
// messages.
// 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.ref() ==
startCongestionCheck) {
SendPing()->Then(eventTarget, __func__, [self, generation]() {
if (generation == self->mFlushedCmdInfo.congestionCheckGeneration) {
// Confirmed IPC messages congestion does not happen.
// Reset flushesSinceLastCongestionCheck for next congestion check.
self->mFlushedCmdInfo.flushesSinceLastCongestionCheck = Some(0);
self->mFlushedCmdInfo.congestionCheckGeneration++;
}
});
} else if (mFlushedCmdInfo.flushesSinceLastCongestionCheck.ref() >
maybeIPCMessageCongestion) {
// IPC messages congestion might happen, send sync SyncPing for flushing
// pending messages.
SendSyncPing();
// Reset flushesSinceLastCongestionCheck for next congestion check.
mFlushedCmdInfo.flushesSinceLastCongestionCheck = Some(0);
mFlushedCmdInfo.congestionCheckGeneration++;
}
// Handle flushesSinceLastCongestionCheck
mFlushedCmdInfo.flushesSinceLastCongestionCheck += 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
// message is not sent in ClientWebGLContext::GetFrontBuffer(). It causes a
// case that a lot of async DispatchCommands messages are sent to
// WebGLParent without calling ClientWebGLContext::GetFrontBuffer(). The
// sending DispatchCommands messages could be faster than receiving message
// at WebGLParent by WebGLParent::RecvDispatchCommands(). If it happens,
// pending IPC messages could grow too much until out of resource. To detect
// the messages congestion, async Ping message is used. If the Ping response
// is not received until maybeIPCMessageCongestion, IPC message might be
// congested at WebGLParent. Then sending sync SyncPing flushes all pending
// messages.
// 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) {
SendPing()->Then(eventTarget, __func__, [self, generation]() {
if (generation == self->mFlushedCmdInfo.congestionCheckGeneration) {
// Confirmed IPC messages congestion does not happen.
// Reset flushesSinceLastCongestionCheck for next congestion check.
self->mFlushedCmdInfo.flushesSinceLastCongestionCheck = 0;
self->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()) {

Просмотреть файл

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