зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
db4ed173eb
Коммит
7998255fe4
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче