/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef WEBGPU_CHILD_H_ #define WEBGPU_CHILD_H_ #include #include #include "mozilla/MozPromise.h" #include "mozilla/WeakPtr.h" #include "mozilla/webgpu/Adapter.h" #include "mozilla/webgpu/Device.h" #include "mozilla/webgpu/Instance.h" #include "mozilla/webgpu/PWebGPUChild.h" #include "mozilla/webgpu/SupportedFeatures.h" #include "mozilla/webgpu/SupportedLimits.h" #include "mozilla/webgpu/ffi/wgpu.h" namespace mozilla { namespace dom { struct GPURequestAdapterOptions; } // namespace dom namespace layers { class CompositorBridgeChild; } // namespace layers namespace webgpu { namespace ffi { struct WGPUClient; struct WGPULimits; struct WGPUTextureViewDescriptor; } // namespace ffi using AdapterPromise = MozPromise, true>; using PipelinePromise = MozPromise; using DevicePromise = MozPromise; ffi::WGPUByteBuf* ToFFI(ipc::ByteBuf* x); struct PendingRequestAdapterPromise { RefPtr promise; RefPtr instance; RawId adapter_id; }; struct PendingRequestDevicePromise { RefPtr promise; RawId device_id; RawId queue_id; nsString label; RefPtr adapter; RefPtr features; RefPtr limits; RefPtr adapter_info; RefPtr lost_promise; }; struct PendingPopErrorScopePromise { RefPtr promise; RefPtr device; }; struct PendingCreatePipelinePromise { RefPtr promise; RefPtr device; bool is_render_pipeline; RawId pipeline_id; nsString label; }; struct PendingCreateShaderModulePromise { RefPtr promise; RefPtr device; RefPtr shader_module; }; struct PendingBufferMapPromise { RefPtr promise; RefPtr buffer; }; /// The child actor is held alive by all WebGPU DOM wrapper objects since it /// provides access to the rust Client; even if it can't send any more /// messages. /// /// It should not take part in cycle collection because the cycle collector can /// be destroyed earlier than IPDL actors; see Bug 1983205. /// /// It also doesn't need to take part in cycle collection even if some of /// its fields contain strong references to DOM wrapper objects because /// we make sure that all cycles are broken either by a server message or /// by `ClearActorState`. class WebGPUChild final : public PWebGPUChild { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebGPUChild, override) public: friend class layers::CompositorBridgeChild; public: explicit WebGPUChild(); RawId RenderBundleEncoderFinish(ffi::WGPURenderBundleEncoder& aEncoder, RawId aDeviceId, const dom::GPURenderBundleDescriptor& aDesc); RawId RenderBundleEncoderFinishError(RawId aDeviceId, const nsString& aLabel); ffi::WGPUClient* GetClient() const { return mClient.get(); } void SwapChainPresent(RawId aTextureId, const RemoteTextureId& aRemoteTextureId, const RemoteTextureOwnerId& aOwnerId); void RegisterDevice(Device* const aDevice); void UnregisterDevice(RawId aDeviceId); void QueueSubmit(RawId aSelfId, RawId aDeviceId, nsTArray& aCommandBuffers, const nsTArray& aUsedExternalTextureSources); void NotifyWaitForSubmit(RawId aTextureId); static void JsWarning(nsIGlobalObject* aGlobal, const nsACString& aMessage); void SendSerializedMessages(uint32_t aNrOfMessages, ipc::ByteBuf aSerializedMessages); private: virtual ~WebGPUChild(); UniquePtr const mClient; /// This is used to relay device lost and uncaptured error messages. /// /// It must hold devices weakly, or else we can end up with cycles that might /// never get broken. This is ok because: /// - device lost messages no longer need to be relayed once there are no /// more external references to the Device, and /// - uncaptured error messages will be relayed since the Device will be /// kept alive if there are any `uncapturederror` event handlers registered /// (see the call to `KeepAliveIfHasListenersFor` in its constructor). std::unordered_map> mDeviceMap; nsTArray mSwapChainTexturesWaitingForSubmit; bool mScheduledFlushQueuedMessages = false; void ScheduledFlushQueuedMessages(); nsTArray mQueuedDataBuffers; nsTArray mQueuedHandles; std::deque mPendingRequestAdapterPromises; std::deque mPendingRequestDevicePromises; std::unordered_map> mPendingDeviceLostPromises; std::deque mPendingPopErrorScopePromises; std::deque mPendingCreatePipelinePromises; std::deque mPendingCreateShaderModulePromises; std::unordered_map> mPendingBufferMapPromises; // Pending submitted work done promises for each queue. We must track these // separately for each queue because there are guarantees about the order // different queues will complete their work in. For each queue individually // we know these will be resolved FIFO. std::unordered_map>> mPendingOnSubmittedWorkDonePromises; void ClearActorState(); public: ipc::IPCResult RecvServerMessage(const ipc::ByteBuf& aByteBuf); ipc::IPCResult RecvUncapturedError(RawId aDeviceId, const dom::GPUErrorFilter aType, const nsACString& aMessage); ipc::IPCResult RecvDeviceLost(RawId aDeviceId, uint8_t aReason, const nsACString& aMessage); size_t QueueDataBuffer(ipc::ByteBuf&& bb); size_t QueueShmemHandle(ipc::MutableSharedMemoryHandle&& handle); void ScheduleFlushQueuedMessages(); void FlushQueuedMessages(); void ActorDestroy(ActorDestroyReason) override; void EnqueueRequestAdapterPromise(PendingRequestAdapterPromise&& promise); void EnqueueRequestDevicePromise(PendingRequestDevicePromise&& promise); void RegisterDeviceLostPromise(RawId id, RefPtr& promise); void EnqueuePopErrorScopePromise(PendingPopErrorScopePromise&& promise); void EnqueueCreatePipelinePromise(PendingCreatePipelinePromise&& promise); void EnqueueCreateShaderModulePromise( PendingCreateShaderModulePromise&& promise); void EnqueueBufferMapPromise(RawId id, PendingBufferMapPromise&& promise); void EnqueueOnSubmittedWorkDonePromise(RawId id, RefPtr& promise); PendingRequestAdapterPromise DequeueRequestAdapterPromise(); PendingRequestDevicePromise DequeueRequestDevicePromise(); PendingPopErrorScopePromise DequeuePopErrorScopePromise(); PendingCreatePipelinePromise DequeueCreatePipelinePromise(); PendingCreateShaderModulePromise DequeueCreateShaderModulePromise(); PendingBufferMapPromise DequeueBufferMapPromise(RawId id); RefPtr DequeueOnSubmittedWorkDonePromise(RawId id); }; } // namespace webgpu } // namespace mozilla #endif // WEBGPU_CHILD_H_