Bug 1746538 - Make PWebGPU managed by PCanvasManager. r=kvark

Similar to PWebGL, we want PCanvasManager to manage the PWebGPU
protocol. This will allow us to reuse the machinery that works for both
the main thread, and arbitrary worker threads to create PWebGPU
protocols.

For now, the only owner is still the main thread, so it should work very
similarly as to how it does with PCompositorBridge.

This patch also introduces some quality of life changes, such as making
the protocol ref-counted, and avoiding respinning the wheel for
CanSend() for IPDL actors.

Differential Revision: https://phabricator.services.mozilla.com/D134097
This commit is contained in:
Andrew Osmond 2022-02-02 20:49:23 +00:00
parent 2da2365f75
commit 8f1c963ed3
18 changed files with 46 additions and 139 deletions

View File

@ -12,7 +12,7 @@
#include "ipc/WebGPUTypes.h"
#include "mozilla/webgpu/ffi/wgpu.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/gfx/CanvasManagerChild.h"
namespace mozilla {
namespace webgpu {
@ -24,7 +24,7 @@ already_AddRefed<Instance> Instance::Create(nsIGlobalObject* aOwner) {
RefPtr<WebGPUChild> bridge;
if (gfx::gfxConfig::IsEnabled(gfx::Feature::WEBGPU)) {
bridge = layers::CompositorBridgeChild::Get()->GetWebGPUChild();
bridge = gfx::CanvasManagerChild::Get()->GetWebGPUChild();
if (NS_WARN_IF(!bridge)) {
MOZ_CRASH("Failed to create an IPDL bridge for WebGPU!");
}

View File

@ -16,7 +16,7 @@ using MaybeScopedError from "mozilla/webgpu/WebGPUTypes.h";
include "mozilla/ipc/ByteBufUtils.h";
include "mozilla/webgpu/WebGPUSerialize.h";
include "mozilla/layers/WebRenderMessageUtils.h";
include protocol PCompositorBridge;
include protocol PCanvasManager;
namespace mozilla {
namespace webgpu {
@ -26,9 +26,9 @@ namespace webgpu {
* command from the content process, and a WebGPUParent in the compositor
* process that runs the commands.
*/
async protocol PWebGPU
[RefCounted] async protocol PWebGPU
{
manager PCompositorBridge;
manager PCanvasManager;
parent:
async DeviceAction(RawId selfId, ByteBuf buf);
@ -70,8 +70,6 @@ parent:
async DevicePushErrorScope(RawId selfId);
async DevicePopErrorScope(RawId selfId) returns (MaybeScopedError maybeError);
async Shutdown();
child:
async DeviceUncapturedError(RawId aDeviceId, nsCString message);
async DropAction(ByteBuf buf);

View File

@ -164,7 +164,7 @@ static ffi::WGPUClient* initialize() {
return infra.client;
}
WebGPUChild::WebGPUChild() : mClient(initialize()), mIPCOpen(false) {}
WebGPUChild::WebGPUChild() : mClient(initialize()) {}
WebGPUChild::~WebGPUChild() {
if (mClient) {

View File

@ -49,12 +49,12 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
friend class layers::CompositorBridgeChild;
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WebGPUChild)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGPUChild)
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING_INHERITED(WebGPUChild)
public:
explicit WebGPUChild();
bool IsOpen() const { return mIPCOpen; }
bool IsOpen() const { return CanSend(); }
RefPtr<AdapterPromise> InstanceRequestAdapter(
const dom::GPURequestAdapterOptions& aOptions);
@ -124,24 +124,7 @@ class WebGPUChild final : public PWebGPUChild, public SupportsWeakPtr {
const dom::GPURenderPipelineDescriptor& aDesc,
ipc::ByteBuf* const aByteBuf);
// AddIPDLReference and ReleaseIPDLReference are only to be called by
// CompositorBridgeChild's AllocPWebGPUChild and DeallocPWebGPUChild methods
// respectively. We intentionally make them private to prevent misuse.
// The purpose of these methods is to be aware of when the IPC system around
// this actor goes down: mIPCOpen is then set to false.
void AddIPDLReference() {
MOZ_ASSERT(!mIPCOpen);
mIPCOpen = true;
AddRef();
}
void ReleaseIPDLReference() {
MOZ_ASSERT(mIPCOpen);
mIPCOpen = false;
Release();
}
ffi::WGPUClient* const mClient;
bool mIPCOpen;
std::unordered_map<RawId, WeakPtr<Device>> mDeviceMap;
public:

View File

@ -738,7 +738,7 @@ ipc::IPCResult WebGPUParent::RecvSwapChainDestroy(
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvShutdown() {
void WebGPUParent::ActorDestroy(ActorDestroyReason aWhy) {
mTimer.Stop();
for (const auto& p : mCanvasMap) {
const wr::ExternalImageId extId = {p.first};
@ -747,7 +747,6 @@ ipc::IPCResult WebGPUParent::RecvShutdown() {
mCanvasMap.clear();
ffi::wgpu_server_poll_all_devices(mContext, true);
ffi::wgpu_server_delete(const_cast<ffi::WGPUGlobal*>(mContext));
return IPC_OK();
}
ipc::IPCResult WebGPUParent::RecvDeviceAction(RawId aSelf,

View File

@ -21,7 +21,7 @@ struct ErrorScopeStack {
};
class WebGPUParent final : public PWebGPUParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGPUParent)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGPUParent, override)
public:
explicit WebGPUParent();
@ -90,7 +90,7 @@ class WebGPUParent final : public PWebGPUParent {
ipc::IPCResult RecvDevicePopErrorScope(
RawId aSelfId, DevicePopErrorScopeResolver&& aResolver);
ipc::IPCResult RecvShutdown();
void ActorDestroy(ActorDestroyReason aWhy) override;
private:
virtual ~WebGPUParent();

View File

@ -11,6 +11,7 @@
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/CompositorManagerChild.h"
#include "mozilla/webgpu/WebGPUChild.h"
using namespace mozilla::dom;
using namespace mozilla::layers;
@ -131,6 +132,17 @@ void CanvasManagerChild::Destroy() {
return manager;
}
RefPtr<webgpu::WebGPUChild> CanvasManagerChild::GetWebGPUChild() {
if (!mWebGPUChild) {
mWebGPUChild = MakeAndAddRef<webgpu::WebGPUChild>();
if (!SendPWebGPUConstructor(mWebGPUChild)) {
mWebGPUChild = nullptr;
}
}
return mWebGPUChild;
}
already_AddRefed<DataSourceSurface> CanvasManagerChild::GetSnapshot(
uint32_t aManagerId, int32_t aProtocolId, bool aHasAlpha) {
if (!CanSend()) {

View File

@ -16,6 +16,10 @@ class IPCWorkerRef;
class WorkerPrivate;
} // namespace dom
namespace webgpu {
class WebGPUChild;
} // namespace webgpu
namespace gfx {
class DataSourceSurface;
@ -35,11 +39,14 @@ class CanvasManagerChild final : public PCanvasManagerChild {
static bool CreateParent(
mozilla::ipc::Endpoint<PCanvasManagerParent>&& aEndpoint);
RefPtr<webgpu::WebGPUChild> GetWebGPUChild();
private:
~CanvasManagerChild();
void Destroy();
RefPtr<mozilla::dom::IPCWorkerRef> mWorkerRef;
RefPtr<webgpu::WebGPUChild> mWebGPUChild;
const uint32_t mId;
static MOZ_THREAD_LOCAL(CanvasManagerChild*) sLocalManager;

View File

@ -9,6 +9,7 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/webgpu/WebGPUParent.h"
#include "mozilla/webrender/RenderThread.h"
#include "nsIThread.h"
@ -87,6 +88,11 @@ already_AddRefed<dom::PWebGLParent> CanvasManagerParent::AllocPWebGLParent() {
return MakeAndAddRef<dom::WebGLParent>();
}
already_AddRefed<webgpu::PWebGPUParent>
CanvasManagerParent::AllocPWebGPUParent() {
return MakeAndAddRef<webgpu::WebGPUParent>();
}
mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize(
const uint32_t& aId) {
if (!aId) {

View File

@ -23,7 +23,10 @@ class CanvasManagerParent final : public PCanvasManagerParent {
void Bind(Endpoint<PCanvasManagerParent>&& aEndpoint);
void ActorDestroy(ActorDestroyReason aWhy) override;
already_AddRefed<PWebGLParent> AllocPWebGLParent();
already_AddRefed<PWebGPUParent> AllocPWebGPUParent();
mozilla::ipc::IPCResult RecvInitialize(const uint32_t& aId);
mozilla::ipc::IPCResult RecvGetSnapshot(
const uint32_t& aManagerId, const int32_t& aProtocolId,

View File

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PWebGL;
include protocol PWebGPU;
using mozilla::webgl::FrontBufferSnapshotIpc from "mozilla/dom/WebGLIpdl.h";
@ -21,11 +22,15 @@ namespace gfx {
[RefCounted] sync protocol PCanvasManager
{
manages PWebGL;
manages PWebGPU;
parent:
// Actor that represents one WebGL context.
async PWebGL();
// Actor that represents one WebGPU context.
async PWebGPU();
// Set the local manager ID for the canvas manager.
async Initialize(uint32_t aManagerId);

View File

@ -26,7 +26,6 @@
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/webgpu/WebGPUChild.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/Telemetry.h"
#include "gfxConfig.h"
@ -177,12 +176,6 @@ void CompositorBridgeChild::Destroy() {
Unused << child->SendDestroy();
}
AutoTArray<PWebGPUChild*, 16> webGPUChildren;
ManagedPWebGPUChild(webGPUChildren);
for (PWebGPUChild* child : webGPUChildren) {
Unused << child->SendShutdown();
}
const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild();
for (const auto& key : textures) {
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(key);
@ -580,16 +573,6 @@ void CompositorBridgeChild::EndCanvasTransaction() {
}
}
RefPtr<webgpu::WebGPUChild> CompositorBridgeChild::GetWebGPUChild() {
MOZ_ASSERT(gfx::gfxConfig::IsEnabled(gfx::Feature::WEBGPU));
if (!mWebGPUChild) {
webgpu::PWebGPUChild* bridge = SendPWebGPUConstructor();
mWebGPUChild = static_cast<webgpu::WebGPUChild*>(bridge);
}
return mWebGPUChild;
}
bool CompositorBridgeChild::AllocUnsafeShmem(
size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem) {
@ -672,18 +655,6 @@ bool CompositorBridgeChild::DeallocPWebRenderBridgeChild(
return true;
}
webgpu::PWebGPUChild* CompositorBridgeChild::AllocPWebGPUChild() {
webgpu::WebGPUChild* child = new webgpu::WebGPUChild();
child->AddIPDLReference();
return child;
}
bool CompositorBridgeChild::DeallocPWebGPUChild(webgpu::PWebGPUChild* aActor) {
webgpu::WebGPUChild* child = static_cast<webgpu::WebGPUChild*>(aActor);
child->ReleaseIPDLReference();
return true;
}
uint64_t CompositorBridgeChild::GetNextResourceId() {
++mResourceId;
MOZ_RELEASE_ASSERT(mResourceId != UINT32_MAX);

View File

@ -29,11 +29,6 @@ namespace dom {
class BrowserChild;
} // namespace dom
namespace webgpu {
class PWebGPUChild;
class WebGPUChild;
} // namespace webgpu
namespace widget {
class CompositorWidget;
} // namespace widget
@ -111,8 +106,6 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
void EndCanvasTransaction();
RefPtr<webgpu::WebGPUChild> GetWebGPUChild();
// Beware that these methods don't override their super-class equivalent
// (which are not virtual), they just overload them. All of these Send*
// methods just add a sanity check (that it is not too late send a message)
@ -182,9 +175,6 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
const WindowKind&);
bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor);
webgpu::PWebGPUChild* AllocPWebGPUChild();
bool DeallocPWebGPUChild(webgpu::PWebGPUChild* aActor);
wr::MaybeExternalImageId GetNextExternalImageId() override;
wr::PipelineId GetNextPipelineId();
@ -258,8 +248,6 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
nsTArray<RefPtr<TextureClient>> mTextureClientsForAsyncPaint;
RefPtr<CanvasChild> mCanvasChild;
RefPtr<webgpu::WebGPUChild> mWebGPUChild;
};
} // namespace layers

View File

@ -57,7 +57,6 @@
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/AsyncImagePipelineManager.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webgpu/WebGPUParent.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
#include "mozilla/mozalloc.h" // for operator new, etc
@ -1289,28 +1288,6 @@ bool CompositorBridgeParent::DeallocPWebRenderBridgeParent(
return true;
}
webgpu::PWebGPUParent* CompositorBridgeParent::AllocPWebGPUParent() {
// This should only ever get called in the GPU process.
MOZ_ASSERT(XRE_IsGPUProcess());
// Shouldn't re-initialize
MOZ_ASSERT(!mWebGPUBridge);
// We should only ever get this if WebGPU is enabled in this compositor.
MOZ_RELEASE_ASSERT(mOptions.UseWebGPU());
mWebGPUBridge = new webgpu::WebGPUParent();
mWebGPUBridge.get()->AddRef(); // IPDL reference
return mWebGPUBridge;
}
bool CompositorBridgeParent::DeallocPWebGPUParent(
webgpu::PWebGPUParent* aActor) {
webgpu::WebGPUParent* parent = static_cast<webgpu::WebGPUParent*>(aActor);
MOZ_ASSERT(mWebGPUBridge == parent);
parent->Release(); // IPDL reference
mWebGPUBridge = nullptr;
return true;
}
void CompositorBridgeParent::NotifyMemoryPressure() {
if (mWrBridge) {
RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();

View File

@ -50,11 +50,6 @@ class ProtocolFuzzerHelper;
#endif
} // namespace ipc
namespace webgpu {
class PWebGPUParent;
class WebGPUParent;
} // namespace webgpu
namespace widget {
class CompositorWidget;
}
@ -207,9 +202,6 @@ class CompositorBridgeParentBase : public PCompositorBridgeParent,
virtual bool DeallocPWebRenderBridgeParent(
PWebRenderBridgeParent* aActor) = 0;
virtual webgpu::PWebGPUParent* AllocPWebGPUParent() = 0;
virtual bool DeallocPWebGPUParent(webgpu::PWebGPUParent* aActor) = 0;
virtual PCompositorWidgetParent* AllocPCompositorWidgetParent(
const CompositorWidgetInitData& aInitData) = 0;
virtual bool DeallocPCompositorWidgetParent(
@ -555,9 +547,6 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
RefPtr<WebRenderBridgeParent> GetWebRenderBridgeParent() const;
Maybe<TimeStamp> GetTestingTimeStamp() const;
webgpu::PWebGPUParent* AllocPWebGPUParent() override;
bool DeallocPWebGPUParent(webgpu::PWebGPUParent* aActor) override;
static CompositorBridgeParent* GetCompositorBridgeParentFromLayersId(
const LayersId& aLayersId);
static RefPtr<CompositorBridgeParent> GetCompositorBridgeParentFromWindowId(
@ -572,7 +561,6 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
LayersId aLayersId);
WebRenderBridgeParent* GetWrBridge() { return mWrBridge; }
webgpu::WebGPUParent* GetWebGPUBridge() { return mWebGPUBridge; }
private:
void Initialize();
@ -686,7 +674,6 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
RefPtr<Compositor> mCompositor;
RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
RefPtr<WebRenderBridgeParent> mWrBridge;
RefPtr<webgpu::WebGPUParent> mWebGPUBridge;
widget::CompositorWidget* mWidget;
Maybe<TimeStamp> mTestTime;
CSSToLayoutDeviceScale mScale;

View File

@ -24,7 +24,6 @@
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/AsyncImagePipelineManager.h"
#include "mozilla/webgpu/WebGPUParent.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsDebug.h" // for NS_ASSERTION, etc
#include "nsTArray.h" // for nsTArray
@ -205,19 +204,6 @@ bool ContentCompositorBridgeParent::DeallocPWebRenderBridgeParent(
return true;
}
webgpu::PWebGPUParent* ContentCompositorBridgeParent::AllocPWebGPUParent() {
webgpu::WebGPUParent* parent = new webgpu::WebGPUParent();
parent->AddRef(); // IPDL reference
return parent;
}
bool ContentCompositorBridgeParent::DeallocPWebGPUParent(
webgpu::PWebGPUParent* aActor) {
webgpu::WebGPUParent* parent = static_cast<webgpu::WebGPUParent*>(aActor);
parent->Release(); // IPDL reference
return true;
}
mozilla::ipc::IPCResult ContentCompositorBridgeParent::RecvNotifyChildCreated(
const LayersId& child, CompositorOptions* aOptions) {
MonitorAutoLock lock(*sIndirectLayerTreesLock);

View File

@ -12,12 +12,7 @@
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
namespace webgpu {
class PWebGPUParent;
} // namespace webgpu
namespace layers {
namespace mozilla::layers {
class CompositorOptions;
@ -169,9 +164,6 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
const WindowKind& aWindowKind) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
webgpu::PWebGPUParent* AllocPWebGPUParent() override;
bool DeallocPWebGPUParent(webgpu::PWebGPUParent* aActor) override;
void ObserveLayersUpdate(LayersId aLayersId, LayersObserverEpoch aEpoch,
bool aActive) override;
@ -196,7 +188,6 @@ class ContentCompositorBridgeParent final : public CompositorBridgeParentBase {
RefPtr<CanvasTranslator> mCanvasTranslator;
};
} // namespace layers
} // namespace mozilla
} // namespace mozilla::layers
#endif // mozilla_layers_ContentCompositorBridgeParent_h

View File

@ -17,7 +17,6 @@ include protocol PCompositorManager;
include protocol PCompositorWidget;
include protocol PTexture;
include protocol PWebRenderBridge;
include protocol PWebGPU;
include "mozilla/GfxMessageUtils.h";
include "mozilla/layers/LayersMessageUtils.h";
include "mozilla/layers/WebRenderMessageUtils.h";
@ -98,7 +97,6 @@ struct FrameStats {
manages PTexture;
manages PCompositorWidget;
manages PWebRenderBridge;
manages PWebGPU;
child:
// The child should invalidate retained layers. This is used for local
@ -139,10 +137,6 @@ parent:
async PAPZ(LayersId layersId);
async PAPZCTreeManager(LayersId layersId);
// Constructor for WebGPU IPDL
// Must be called before Initialize().
async PWebGPU();
// The child is about to be destroyed, so perform any necessary cleanup.
sync WillClose();