WebKit icon indicating copy to clipboard operation
WebKit copied to clipboard

Add WorkerClient for WebCore to access WebKit from worker threads, and use it to create a RemoteRenderingBackendProxy per-thread

Open mattwoodrow opened this issue 3 years ago โ€ข 7 comments

73a4c71642dfa90e574348729f4cfd8beb3ee2dc

Add WorkerClient for WebCore to access WebKit from worker threads, and use it to create a RemoteRenderingBackendProxy per-thread
https://bugs.webkit.org/show_bug.cgi?id=244828

Reviewed by NOBODY (OOPS!).

The primary design goal here is to avoid having classes that are accessed from multiple threads (and need locking), and instead to have
per-thread instances with separate state.

Creates new subclass for HostWindow 'GraphicsClient', for the graphics specific subset. This currently only has createImageBuffer, but in the future
will have other graphics-related WebKit functionality (like creating a WebGL context).

Creates a new interface class WorkerClient (which implements GraphicsClient), for accessing WebKit graphics APIs from a worker thread. Adds an implementation
of this in WebWorkerClient.

Allocates an instance of (Web)WorkerClient for every dedicated and shared worker, and makes it available via WorkerGlobalScope.

WebWorkerClient creates a dedicated GPUProcessConnection and RemoteRenderingBackendProx for each worker thread/instance, and uses this to create
RemoteImageBufferProxys that are safe to use on that worker thread.

GPUProcess updated to handle multiple instances of GPUConnectionToWebProcess per web process, by storing both the primary connection (connected
to the main thread of the web process), and a list of secondary connections (for workers).

ImageBitmap::createImageBuffer has been updated to determine the appropriate GraphicsClient for the thread from the ScriptExecutionContext, and uses that
when allocating buffers, so that we get GPUP backed image buffers for workers.

* Source/WebCore/Headers.cmake:
* Source/WebCore/html/ImageBitmap.cpp:
(WebCore::ImageBitmap::createImageBuffer):
* Source/WebCore/page/Chrome.cpp:
(WebCore::Chrome::createWorkerClient):
* Source/WebCore/page/Chrome.h:
* Source/WebCore/page/ChromeClient.h:
(WebCore::ChromeClient::createWorkerClient):
* Source/WebCore/page/WorkerClient.h: Added.
* Source/WebCore/platform/GraphicsClient.h: Added.
* Source/WebCore/workers/DedicatedWorkerThread.cpp:
(WebCore::DedicatedWorkerThread::createWorkerGlobalScope):
* Source/WebCore/workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::setWorkerClient):
* Source/WebCore/workers/WorkerGlobalScope.h:
(WebCore::WorkerGlobalScope::getWorkerClient):
* Source/WebCore/workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::startWorkerGlobalScope):
* Source/WebCore/workers/WorkerThread.h:
(WebCore::WorkerThread::setWorkerClient):
(WebCore::WorkerThread::workerClient):
* Source/WebCore/workers/shared/context/SharedWorkerThread.cpp:
(WebCore::SharedWorkerThread::createWorkerGlobalScope):
* Source/WebCore/workers/shared/context/SharedWorkerThreadProxy.cpp:
(WebCore::SharedWorkerThreadProxy::SharedWorkerThreadProxy):
* Source/WebKit/GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::createGPUConnectionToWebProcess):
(WebKit::GPUProcess::removeGPUConnectionToWebProcess):
(WebKit::GPUProcess::canExitUnderMemoryPressure const):
(WebKit::GPUProcess::lowMemoryHandler):
(WebKit::GPUProcess::webProcessConnection const):
(WebKit::GPUProcess::extraWebProcessConnections const):
(WebKit::GPUProcess::setOrientationForMediaCapture):
(WebKit::GPUProcess::displayConfigurationChanged):
(WebKit::GPUProcess::processIsStartingToCaptureAudio):
(WebKit::GPUProcess::requestBitmapImageForCurrentTime):
* Source/WebKit/GPUProcess/GPUProcess.h:
* Source/WebKit/GPUProcess/cocoa/GPUProcessCocoa.mm:
(WebKit::GPUProcess::additionalStateForDiagnosticReport const):
* Source/WebKit/Platform/IPC/StreamClientConnection.cpp:
(IPC::StreamClientConnection::open):
* Source/WebKit/Platform/IPC/StreamClientConnection.h:
* Source/WebKit/Shared/GPUProcessConnectionParameters.h:
(WebKit::GPUProcessConnectionParameters::encode const):
(WebKit::GPUProcessConnectionParameters::decode):
* Source/WebKit/Sources.txt:
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
* Source/WebKit/WebProcess/GPU/GPUProcessConnection.cpp:
(WebKit::GPUProcessConnection::create):
(WebKit::GPUProcessConnection::GPUProcessConnection):
* Source/WebKit/WebProcess/GPU/GPUProcessConnection.h:
* Source/WebKit/WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.cpp:
(WebKit::RemoteGraphicsContextGLProxy::RemoteGraphicsContextGLProxy):
* Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
(WebKit::RemoteRenderingBackendProxy::create):
(WebKit::RemoteRenderingBackendProxy::RemoteRenderingBackendProxy):
(WebKit::RemoteRenderingBackendProxy::ensureGPUProcessConnection):
* Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.h:
* Source/WebKit/WebProcess/GPU/graphics/WebGPU/RemoteGPUProxy.cpp:
(WebKit::RemoteGPUProxy::RemoteGPUProxy):
* Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::createWorkerClient):
* Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h:
* Source/WebKit/WebProcess/WebCoreSupport/WebWorkerClient.cpp: Added.
(WebKit::WebWorkerClient::WebWorkerClient):
(WebKit::WebWorkerClient::ensureRenderingBackend const):
(WebKit::WebWorkerClient::clone):
(WebKit::WebWorkerClient::displayID const):
(WebKit::WebWorkerClient::createImageBuffer const):
* Source/WebKit/WebProcess/WebCoreSupport/WebWorkerClient.h: Added.
* Source/WebKit/WebProcess/WebProcess.cpp:
(WebKit::WebProcess::createGPUProcessConnection):
* Source/WebKit/WebProcess/WebProcess.h:
* Tools/TestWebKitAPI/Tests/IPC/StreamConnectionTests.cpp:
(TestWebKitAPI::TEST_F):

2974d64e695f2019961aea93fc1d0aebb3931223

Create GraphicsClient for the graphics specific subset of ChromeClient that needs to be accessed from worker threads.
https://bugs.webkit.org/show_bug.cgi?id=244828

Reviewed by NOBODY (OOPS!).

* Source/WebCore/Headers.cmake:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/css/CSSFilterImageValue.cpp:
* Source/WebCore/html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::createImageBuffer const):
* Source/WebCore/html/ImageBitmap.cpp:
(WebCore::ImageBitmap::createImageBuffer):
(WebCore::ImageBitmap::createPromise):
* Source/WebCore/html/ImageBitmap.h:
* Source/WebCore/html/OffscreenCanvas.cpp:
(WebCore::OffscreenCanvas::transferToImageBitmap):
(WebCore::OffscreenCanvas::createImageBuffer const):
* Source/WebCore/page/Chrome.h:
* Source/WebCore/platform/HostWindow.h:
* Source/WebCore/platform/graphics/ImageBuffer.cpp:
(WebCore::ImageBuffer::create):
* Source/WebCore/platform/graphics/ImageBuffer.h:
(WebCore::ImageBuffer::CreationContext::CreationContext):
* Source/WebCore/platform/graphics/cg/ImageBufferIOSurfaceBackend.cpp:
(WebCore::ImageBufferIOSurfaceBackend::create):
* Source/WebCore/platform/graphics/cocoa/IOSurface.h:
* Source/WebCore/platform/graphics/cocoa/IOSurface.mm:
(WebCore::IOSurface::ensurePlatformContext):

0f1b2d34f5b8fd3655cecfdda9fc656b46564445

Allow creating IPC::Connection with a SerialFunctionDispatcher other than the main RunLoop.
https://bugs.webkit.org/show_bug.cgi?id=244825

Reviewed by NOBODY (OOPS!).

* Source/WebKit/Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageStateImpl::enqueueMatchingMessages):
(IPC::Connection::SyncMessageStateImpl::processIncomingMessage):
(IPC::Connection::SyncMessageStateImpl::dispatchMessages):
(IPC::Connection::SyncMessageStateImpl::dispatchMessagesAndResetDidScheduleDispatchMessagesForConnection):
(IPC::Connection::createServerConnection):
(IPC::Connection::Connection):
(IPC::Connection::~Connection):
(IPC::Connection::connection):
(IPC::Connection::enqueueMatchingMessagesToMessageReceiveQueue):
(IPC::Connection::invalidate):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::processIncomingMessage):
(IPC::Connection::enableIncomingMessagesThrottling):
(IPC::Connection::connectionDidClose):
(IPC::Connection::dispatchSyncMessage):
(IPC::Connection::dispatchDidReceiveInvalidMessage):
(IPC::Connection::enqueueIncomingMessage):
(IPC::Connection::dispatchMessage):
(IPC::Connection::dispatchIncomingMessages):
(IPC::Connection::wakeUpRunLoop):
* Source/WebKit/Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
(IPC::Connection::waitForAsyncCallbackAndDispatchImmediately):

508461b6877e2c9f6c7b7875422d791c17d715f3

Don't force CompletionHandlerCallThread::MainThread for async replies
https://bugs.webkit.org/show_bug.cgi?id=246308

Reviewed by NOBODY (OOPS!).

This only changes an assertion, doesn't affect behaviour at all.

* Source/WebKit/Platform/IPC/Connection.h:
(IPC::Connection::sendWithAsyncReply):

c3b87699d4881942d8684b390236315333005a3a

Add SerialFunctionDispatcher interface.
https://bugs.webkit.org/show_bug.cgi?id=246305

Reviewed by NOBODY (OOPS!).

This creates a common interface between RunLoop, and WorkerOrWorkletThread, that lets you dispatch Functions
that are guaranteed to be executed serially.

* Source/WTF/wtf/FunctionDispatcher.h:
(WTF::WTF_ASSERTS_ACQUIRED_CAPABILITY):
* Source/WTF/wtf/RunLoop.cpp:
(WTF::RunLoop::assertIsCurrent const):
* Source/WTF/wtf/RunLoop.h:
* Source/WebCore/workers/WorkerOrWorkletThread.cpp:
(WebCore::WorkerOrWorkletThread::dispatch):
(WebCore::WorkerOrWorkletThread::assertIsCurrent const):
* Source/WebCore/workers/WorkerOrWorkletThread.h:

https://github.com/WebKit/WebKit/commit/73a4c71642dfa90e574348729f4cfd8beb3ee2dc

Misc iOS, tvOS & watchOS macOS Linux Windows
โœ… ๐Ÿงช style โœ… ๐Ÿ›  ios โœ… ๐Ÿ›  mac โŒ ๐Ÿ›  wpe โŒ ๐Ÿ›  ๐Ÿงช win
โœ… ๐Ÿงช bindings โœ… ๐Ÿ›  ios-sim โœ… ๐Ÿ›  mac-debug โŒ ๐Ÿ›  gtk โŒ ๐Ÿ›  wincairo
โœ… ๐Ÿงช webkitperl โŒ ๐Ÿงช ios-wk2 โœ… ๐Ÿ›  mac-AS-debug โŒ ๐Ÿงช gtk-wk2
โŒ ๐Ÿงช api-ios โ€ƒ ~~๐Ÿงช api-mac~~ โŒ ๐Ÿงช api-gtk
โœ… ๐Ÿ›  ๐Ÿงช jsc โœ… ๐Ÿ›  tv โœ… ๐Ÿงช mac-wk1 โœ… ๐Ÿ›  jsc-armv7
โœ… ๐Ÿ›  tv-sim โŒ ๐Ÿงช mac-wk2 โœ… ๐Ÿงช jsc-armv7-tests
โœ… ๐Ÿ›  watch โŒ ๐Ÿงช mac-AS-debug-wk2 โœ… ๐Ÿ›  jsc-mips
โœ… ๐Ÿ›  watch-sim โœ… ๐Ÿงช mac-wk2-stress โœ… ๐Ÿงช jsc-mips-tests

mattwoodrow avatar Sep 07 '22 02:09 mattwoodrow

Full branch for extra context: https://github.com/mattwoodrow/WebKit/commits/eng/remote-rendering-workers

mattwoodrow avatar Sep 07 '22 02:09 mattwoodrow

I think this work could be simplified to first pursue the changes needed with GraphicsClient.

It seems that we are lacking a per-worker factory for polymorphic object instantiations. We have per-page factory ChromeClient that creates objects that depend on global state. We need per-worker factory of similar sort, WorkerClient.

I would start with:

  1. Extract what ImageBuffer/WebGL needs from ChromeClient to GraphicsClient, make it work with current code.

2a. Investigate what is the object that workers use to configure the polymorphic objects via the global state. If there is none, add this interface

alternatively

2b. Add logic for ChromeClient to hold per-thread GraphicsClients

Small detail: I suppose the ScriptExecutionContext would be the place to add the initial polymorphic query to get the GraphicsClient?

E.g. there's ScriptExecutionContext::notificationClient(), and similar to this, there could be one for graphics?

Things that initially do not make sense to me:

GPUProcess updated to handle multiple instances of GPUConnectionToWebProcess per web process

This does not seem to be needed. To me, it appears as if we just need a RemoteRenderingBackendProxy per worker. Then we just need to make sure that the closure/crash support works if it doesn't work with the main connection.

SerialDispatchQueue -- We already have WorkQueue, which is a serial dispatch queue. So the code about that doesn't make sense initially. Note: the implementation seems to be missing from this patch.

kkinnunen-apple avatar Sep 12 '22 12:09 kkinnunen-apple

Things that initially do not make sense to me:

GPUProcess updated to handle multiple instances of GPUConnectionToWebProcess per web process

This does not seem to be needed. To me, it appears as if we just need a RemoteRenderingBackendProxy per worker. Then we just need to make sure that the closure/crash support works if it doesn't work with the main connection.

We'd also need to add support to IPC::Connection for sending sync messages from the worker thread, and make sure responses are handled without touching/blocking the main thread. That's pretty complicated, with all the complexity we already have for handling unrelated messages while blocking for a sync message.

Instead, I added support for creating new IPC::Connections that are bound to the worker thread (and can send sync messages from that thread), but don't support the re-entrant message handling (for simplicity, and we don't need that functionality for the current use case).

This does require creating a new GPUConnectionToWebProcess though, bound to the IPC::Connection for the worker.

This is all in https://github.com/WebKit/WebKit/pull/4043 (which is a dependency here, though GitHub doesn't let me express that in a useful way).

SerialDispatchQueue -- We already have WorkQueue, which is a serial dispatch queue. So the code about that doesn't make sense initially. Note: the implementation seems to be missing from this patch.

The implementation is in https://github.com/WebKit/WebKit/pull/4043.

The functionality we're trying to represent here is 'the main thread, or a worker', that we can dispatch tasks to, assert that we're currently running in the expected place, and hold on to a reference to (could be weak, or strong).

WorkQueue is a specific implementation, that neither the main thread or workers are. The closest existing thing that I can find is FunctionDispatcher (which isn't implemented by WorkerOrWorkletThread, but can be), but that doesn't offer refcounting, or assertions.

mattwoodrow avatar Sep 12 '22 21:09 mattwoodrow

SerialDispatchQueue -- We already have WorkQueue, which is a serial dispatch queue. So the code about that doesn't make sense initially. Note: the implementation seems to be missing from this patch.

Note that WorkQueue could implement the SerialDispatchQueue interface, but ConcurrentWorkQueue can't really, so it's a bit tricky.

mattwoodrow avatar Sep 12 '22 22:09 mattwoodrow

Please note, only the top two commits are truly part of this PR. The others are just there because GitHub (and EWS) don't support dependent branches.

mattwoodrow avatar Oct 11 '22 04:10 mattwoodrow

Committed 257507@main (280e6cdf0e10): https://commits.webkit.org/257507@main

Reviewed commits have been landed. Closing PR #4085 and removing active labels.

webkit-commit-queue avatar Dec 07 '22 22:12 webkit-commit-queue