diff --git a/dom/webgpu/Adapter.cpp b/dom/webgpu/Adapter.cpp index 015ad734dbfe..2954ef523add 100644 --- a/dom/webgpu/Adapter.cpp +++ b/dom/webgpu/Adapter.cpp @@ -18,7 +18,7 @@ GPU_IMPL_CYCLE_COLLECTION(Adapter, mParent, mBridge) GPU_IMPL_JS_WRAP(Adapter) Adapter::Adapter(Instance* const aParent, RawId aId) - : ChildOf(aParent), mBridge(aParent->GetBridge()), mId(aId) {} + : ChildOf(aParent), mBridge(aParent->mBridge), mId(aId) {} Adapter::~Adapter() { Cleanup(); } @@ -29,8 +29,6 @@ void Adapter::Cleanup() { } } -WebGPUChild* Adapter::GetBridge() const { return mBridge; } - already_AddRefed Adapter::RequestDevice( const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv) { RefPtr promise = dom::Promise::Create(GetParentObject(), aRv); diff --git a/dom/webgpu/Adapter.h b/dom/webgpu/Adapter.h index 942e17a0b4d1..37853e57efbd 100644 --- a/dom/webgpu/Adapter.h +++ b/dom/webgpu/Adapter.h @@ -29,19 +29,19 @@ class Adapter final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(Adapter) GPU_DECL_JS_WRAP(Adapter) + const RefPtr mBridge; + private: Adapter() = delete; ~Adapter(); void Cleanup(); - const RefPtr mBridge; const RawId mId; const nsString mName; public: explicit Adapter(Instance* const aParent, RawId aId); void GetName(nsString& out) const { out = mName; } - WebGPUChild* GetBridge() const; already_AddRefed RequestDevice( const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv); diff --git a/dom/webgpu/BindGroup.cpp b/dom/webgpu/BindGroup.cpp index f147859607eb..c3b2d4237ed7 100644 --- a/dom/webgpu/BindGroup.cpp +++ b/dom/webgpu/BindGroup.cpp @@ -14,7 +14,20 @@ namespace webgpu { GPU_IMPL_CYCLE_COLLECTION(BindGroup, mParent) GPU_IMPL_JS_WRAP(BindGroup) -void BindGroup::Cleanup() {} +BindGroup::BindGroup(Device* const aParent, RawId aId) + : ChildOf(aParent), mId(aId) {} + +BindGroup::~BindGroup() { Cleanup(); } + +void BindGroup::Cleanup() { + if (mValid && mParent) { + mValid = false; + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyBindGroup(mId); + } + } +} } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/BindGroup.h b/dom/webgpu/BindGroup.h index 926b1164e70d..8ebc2f3754a1 100644 --- a/dom/webgpu/BindGroup.h +++ b/dom/webgpu/BindGroup.h @@ -8,6 +8,7 @@ #include "nsWrapperCache.h" #include "ObjectModel.h" +#include "mozilla/webgpu/WebGPUTypes.h" namespace mozilla { namespace webgpu { @@ -19,9 +20,12 @@ class BindGroup final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(BindGroup) GPU_DECL_JS_WRAP(BindGroup) + BindGroup(Device* const aParent, RawId aId); + + const RawId mId; + private: - BindGroup() = delete; - ~BindGroup() = default; + ~BindGroup(); void Cleanup(); }; diff --git a/dom/webgpu/BindGroupLayout.cpp b/dom/webgpu/BindGroupLayout.cpp index ff9a574032a0..a083ae1f8506 100644 --- a/dom/webgpu/BindGroupLayout.cpp +++ b/dom/webgpu/BindGroupLayout.cpp @@ -14,7 +14,20 @@ namespace webgpu { GPU_IMPL_CYCLE_COLLECTION(BindGroupLayout, mParent) GPU_IMPL_JS_WRAP(BindGroupLayout) -void BindGroupLayout::Cleanup() {} +BindGroupLayout::BindGroupLayout(Device* const aParent, RawId aId) + : ChildOf(aParent), mId(aId) {} + +BindGroupLayout::~BindGroupLayout() { Cleanup(); } + +void BindGroupLayout::Cleanup() { + if (mValid && mParent) { + mValid = false; + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyBindGroupLayout(mId); + } + } +} } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/BindGroupLayout.h b/dom/webgpu/BindGroupLayout.h index 4b6ab7e85027..c9d2e2e52b31 100644 --- a/dom/webgpu/BindGroupLayout.h +++ b/dom/webgpu/BindGroupLayout.h @@ -8,6 +8,7 @@ #include "nsWrapperCache.h" #include "ObjectModel.h" +#include "mozilla/webgpu/WebGPUTypes.h" namespace mozilla { namespace webgpu { @@ -19,9 +20,12 @@ class BindGroupLayout final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(BindGroupLayout) GPU_DECL_JS_WRAP(BindGroupLayout) + BindGroupLayout(Device* const aParent, RawId aId); + + const RawId mId; + private: - BindGroupLayout() = delete; - ~BindGroupLayout() = default; + ~BindGroupLayout(); void Cleanup(); }; diff --git a/dom/webgpu/Buffer.cpp b/dom/webgpu/Buffer.cpp index faeac93ad310..13fd668585fa 100644 --- a/dom/webgpu/Buffer.cpp +++ b/dom/webgpu/Buffer.cpp @@ -51,7 +51,10 @@ Buffer::~Buffer() { void Buffer::Cleanup() { if (mParent) { - mParent->DestroyBuffer(mId); + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyBuffer(mId); + } } mMapping.reset(); } diff --git a/dom/webgpu/Buffer.h b/dom/webgpu/Buffer.h index 7a9d94ebf8a5..65597c7e577c 100644 --- a/dom/webgpu/Buffer.h +++ b/dom/webgpu/Buffer.h @@ -34,11 +34,12 @@ class Buffer final : public ObjectBase, public ChildOf { Buffer(Device* const aParent, RawId aId, BufferAddress aSize); void InitMapping(ipc::Shmem&& aShmem, JSObject* aArrayBuffer); + const RawId mId; + private: virtual ~Buffer(); void Cleanup(); - const RawId mId; // Note: we can't map a buffer with the size that don't fit into `size_t` // (which may be smaller than `BufferAddress`), but general not all buffers // are mapped. diff --git a/dom/webgpu/CommandBuffer.cpp b/dom/webgpu/CommandBuffer.cpp index a111af0572f3..2b8f5a27adfa 100644 --- a/dom/webgpu/CommandBuffer.cpp +++ b/dom/webgpu/CommandBuffer.cpp @@ -26,7 +26,10 @@ CommandBuffer::~CommandBuffer() { Cleanup(); } void CommandBuffer::Cleanup() { if (mValid && mParent) { mValid = false; - mParent->DestroyCommandBuffer(mId); + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyCommandBuffer(mId); + } } } diff --git a/dom/webgpu/CommandEncoder.cpp b/dom/webgpu/CommandEncoder.cpp index 2be1bfb43541..3bec54e849a9 100644 --- a/dom/webgpu/CommandEncoder.cpp +++ b/dom/webgpu/CommandEncoder.cpp @@ -7,6 +7,7 @@ #include "CommandEncoder.h" #include "CommandBuffer.h" +#include "Buffer.h" #include "ComputePassEncoder.h" #include "Device.h" @@ -18,14 +19,29 @@ GPU_IMPL_JS_WRAP(CommandEncoder) CommandEncoder::CommandEncoder(Device* const aParent, WebGPUChild* const aBridge, RawId aId) - : ChildOf(aParent), mBridge(aBridge), mId(aId) {} + : ChildOf(aParent), mId(aId), mBridge(aBridge) {} CommandEncoder::~CommandEncoder() { Cleanup(); } void CommandEncoder::Cleanup() { if (mValid && mParent) { mValid = false; - mParent->DestroyCommandEncoder(mId); + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyCommandEncoder(mId); + } + } +} + +void CommandEncoder::CopyBufferToBuffer(const Buffer& aSource, + BufferAddress aSourceOffset, + const Buffer& aDestination, + BufferAddress aDestinationOffset, + BufferAddress aSize) { + if (mValid) { + mBridge->SendCommandEncoderCopyBufferToBuffer( + mId, aSource.mId, aSourceOffset, aDestination.mId, aDestinationOffset, + aSize); } } diff --git a/dom/webgpu/CommandEncoder.h b/dom/webgpu/CommandEncoder.h index 448789c74f46..6d0ead3e6d35 100644 --- a/dom/webgpu/CommandEncoder.h +++ b/dom/webgpu/CommandEncoder.h @@ -38,20 +38,26 @@ class CommandEncoder final : public ObjectBase, public ChildOf { GPU_DECL_JS_WRAP(CommandEncoder) CommandEncoder(Device* const aParent, WebGPUChild* const aBridge, RawId aId); - RawId GetId() const { return mId; } - void EndComputePass(Span aData, ErrorResult& aRv); - already_AddRefed BeginComputePass( - const dom::GPUComputePassDescriptor& aDesc); - already_AddRefed Finish( - const dom::GPUCommandBufferDescriptor& aDesc); + const RawId mId; private: ~CommandEncoder(); void Cleanup(); const RefPtr mBridge; - const RawId mId; + + public: + void EndComputePass(Span aData, ErrorResult& aRv); + + void CopyBufferToBuffer(const Buffer& aSource, BufferAddress aSourceOffset, + const Buffer& aDestination, + BufferAddress aDestinationOffset, + BufferAddress aSize); + already_AddRefed BeginComputePass( + const dom::GPUComputePassDescriptor& aDesc); + already_AddRefed Finish( + const dom::GPUCommandBufferDescriptor& aDesc); }; } // namespace webgpu diff --git a/dom/webgpu/ComputePassEncoder.cpp b/dom/webgpu/ComputePassEncoder.cpp index 6624339620ab..7459fad68a6a 100644 --- a/dom/webgpu/ComputePassEncoder.cpp +++ b/dom/webgpu/ComputePassEncoder.cpp @@ -5,6 +5,8 @@ #include "mozilla/dom/WebGPUBinding.h" #include "ComputePassEncoder.h" +#include "BindGroup.h" +#include "ComputePipeline.h" #include "mozilla/webgpu/ffi/wgpu.h" @@ -29,7 +31,7 @@ ffi::WGPURawPass BeginComputePass(RawId aEncoderId, ComputePassEncoder::ComputePassEncoder( CommandEncoder* const aParent, const dom::GPUComputePassDescriptor& aDesc) - : ChildOf(aParent), mRaw(BeginComputePass(aParent->GetId(), aDesc)) {} + : ChildOf(aParent), mRaw(BeginComputePass(aParent->mId, aDesc)) {} ComputePassEncoder::~ComputePassEncoder() { if (mValid) { @@ -38,6 +40,22 @@ ComputePassEncoder::~ComputePassEncoder() { } } +void ComputePassEncoder::SetBindGroup( + uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) { + if (mValid) { + ffi::wgpu_compute_pass_set_bind_group(&mRaw, aSlot, aBindGroup.mId, + aDynamicOffsets.Elements(), + aDynamicOffsets.Length()); + } +} + +void ComputePassEncoder::SetPipeline(const ComputePipeline& aPipeline) { + if (mValid) { + ffi::wgpu_compute_pass_set_pipeline(&mRaw, aPipeline.mId); + } +} + void ComputePassEncoder::Dispatch(uint32_t x, uint32_t y, uint32_t z) { if (mValid) { ffi::wgpu_compute_pass_dispatch(&mRaw, x, y, z); diff --git a/dom/webgpu/ComputePassEncoder.h b/dom/webgpu/ComputePassEncoder.h index 28a783f8bebc..461c4f8fb8e2 100644 --- a/dom/webgpu/ComputePassEncoder.h +++ b/dom/webgpu/ComputePassEncoder.h @@ -37,6 +37,9 @@ class ComputePassEncoder final : public ProgrammablePassEncoder, ffi::WGPURawPass mRaw; public: + void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) override; + void SetPipeline(const ComputePipeline& aPipeline); void Dispatch(uint32_t x, uint32_t y, uint32_t z); void EndPass(ErrorResult& aRv); }; diff --git a/dom/webgpu/ComputePipeline.cpp b/dom/webgpu/ComputePipeline.cpp index 65e9151c0dc8..07af34d92b20 100644 --- a/dom/webgpu/ComputePipeline.cpp +++ b/dom/webgpu/ComputePipeline.cpp @@ -13,5 +13,20 @@ namespace webgpu { GPU_IMPL_CYCLE_COLLECTION(ComputePipeline, mParent) GPU_IMPL_JS_WRAP(ComputePipeline) +ComputePipeline::ComputePipeline(Device* const aParent, RawId aId) + : ChildOf(aParent), mId(aId) {} + +ComputePipeline::~ComputePipeline() { Cleanup(); } + +void ComputePipeline::Cleanup() { + if (mValid && mParent) { + mValid = false; + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyComputePipeline(mId); + } + } +} + } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/ComputePipeline.h b/dom/webgpu/ComputePipeline.h index c9d9fae81cc9..02726c5980f2 100644 --- a/dom/webgpu/ComputePipeline.h +++ b/dom/webgpu/ComputePipeline.h @@ -19,10 +19,13 @@ class ComputePipeline final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(ComputePipeline) GPU_DECL_JS_WRAP(ComputePipeline) + ComputePipeline(Device* const aParent, RawId aId); + + const RawId mId; + private: - ComputePipeline() = delete; - ~ComputePipeline() = default; - void Cleanup() {} + ~ComputePipeline(); + void Cleanup(); }; } // namespace webgpu diff --git a/dom/webgpu/Device.cpp b/dom/webgpu/Device.cpp index a8bca0703374..54714dbbaa94 100644 --- a/dom/webgpu/Device.cpp +++ b/dom/webgpu/Device.cpp @@ -38,9 +38,9 @@ JSObject* Device::CreateExternalArrayBuffer(JSContext* aCx, size_t aSize, Device::Device(Adapter* const aParent, RawId aId) : DOMEventTargetHelper(aParent->GetParentObject()), - mBridge(aParent->GetBridge()), + mBridge(aParent->mBridge), mId(aId), - mQueue(new Queue(this, aParent->GetBridge(), aId)) {} + mQueue(new Queue(this, aParent->mBridge, aId)) {} Device::~Device() { Cleanup(); } @@ -129,12 +129,6 @@ void Device::UnmapBuffer(RawId aId, UniquePtr aShmem) { mBridge->SendDeviceUnmapBuffer(mId, aId, std::move(*aShmem)); } -void Device::DestroyBuffer(RawId aId) { - if (mBridge && mBridge->IsOpen()) { - mBridge->DestroyBuffer(aId); - } -} - already_AddRefed Device::CreateCommandEncoder( const dom::GPUCommandEncoderDescriptor& aDesc) { RawId id = mBridge->DeviceCreateCommandEncoder(mId, aDesc); @@ -142,16 +136,37 @@ already_AddRefed Device::CreateCommandEncoder( return encoder.forget(); } -void Device::DestroyCommandEncoder(RawId aId) { - if (mBridge && mBridge->IsOpen()) { - mBridge->DestroyCommandEncoder(aId); - } +already_AddRefed Device::CreateBindGroupLayout( + const dom::GPUBindGroupLayoutDescriptor& aDesc) { + RawId id = mBridge->DeviceCreateBindGroupLayout(mId, aDesc); + RefPtr object = new BindGroupLayout(this, id); + return object.forget(); +} +already_AddRefed Device::CreatePipelineLayout( + const dom::GPUPipelineLayoutDescriptor& aDesc) { + RawId id = mBridge->DeviceCreatePipelineLayout(mId, aDesc); + RefPtr object = new PipelineLayout(this, id); + return object.forget(); +} +already_AddRefed Device::CreateBindGroup( + const dom::GPUBindGroupDescriptor& aDesc) { + RawId id = mBridge->DeviceCreateBindGroup(mId, aDesc); + RefPtr object = new BindGroup(this, id); + return object.forget(); } -void Device::DestroyCommandBuffer(RawId aId) { - if (mBridge && mBridge->IsOpen()) { - mBridge->DestroyCommandBuffer(aId); - } +already_AddRefed Device::CreateShaderModule( + const dom::GPUShaderModuleDescriptor& aDesc) { + RawId id = mBridge->DeviceCreateShaderModule(mId, aDesc); + RefPtr object = new ShaderModule(this, id); + return object.forget(); +} + +already_AddRefed Device::CreateComputePipeline( + const dom::GPUComputePipelineDescriptor& aDesc) { + RawId id = mBridge->DeviceCreateComputePipeline(mId, aDesc); + RefPtr object = new ComputePipeline(this, id); + return object.forget(); } } // namespace webgpu diff --git a/dom/webgpu/Device.h b/dom/webgpu/Device.h index fcc7cae4f27d..935de12cb016 100644 --- a/dom/webgpu/Device.h +++ b/dom/webgpu/Device.h @@ -79,15 +79,13 @@ class Device final : public DOMEventTargetHelper { RefPtr MapBufferForReadAsync(RawId aId, size_t aSize, ErrorResult& aRv); void UnmapBuffer(RawId aId, UniquePtr aShmem); - void DestroyBuffer(RawId aId); - void DestroyCommandEncoder(RawId aId); - void DestroyCommandBuffer(RawId aId); + + const RefPtr mBridge; private: ~Device(); void Cleanup(); - const RefPtr mBridge; const RawId mId; bool mValid = true; nsString mLabel; @@ -105,6 +103,19 @@ class Device final : public DOMEventTargetHelper { already_AddRefed CreateCommandEncoder( const dom::GPUCommandEncoderDescriptor& aDesc); + + already_AddRefed CreateBindGroupLayout( + const dom::GPUBindGroupLayoutDescriptor& aDesc); + already_AddRefed CreatePipelineLayout( + const dom::GPUPipelineLayoutDescriptor& aDesc); + already_AddRefed CreateBindGroup( + const dom::GPUBindGroupDescriptor& aDesc); + + already_AddRefed CreateShaderModule( + const dom::GPUShaderModuleDescriptor& aDesc); + already_AddRefed CreateComputePipeline( + const dom::GPUComputePipelineDescriptor& aDesc); + // IMPL_EVENT_HANDLER(uncapturederror) }; diff --git a/dom/webgpu/Instance.cpp b/dom/webgpu/Instance.cpp index 33e874f9c842..de3b916e91db 100644 --- a/dom/webgpu/Instance.cpp +++ b/dom/webgpu/Instance.cpp @@ -15,7 +15,7 @@ namespace mozilla { namespace webgpu { -GPU_IMPL_CYCLE_COLLECTION(Instance, mOwner, mBridge) +GPU_IMPL_CYCLE_COLLECTION(Instance, mBridge, mOwner) /*static*/ already_AddRefed Instance::Create(nsIGlobalObject* aOwner) { @@ -34,7 +34,7 @@ already_AddRefed Instance::Create(nsIGlobalObject* aOwner) { } Instance::Instance(nsIGlobalObject* aOwner, WebGPUChild* aBridge) - : mOwner(aOwner), mBridge(aBridge) {} + : mBridge(aBridge), mOwner(aOwner) {} Instance::~Instance() { Cleanup(); } @@ -45,8 +45,6 @@ JSObject* Instance::WrapObject(JSContext* cx, return dom::GPU_Binding::Wrap(cx, this, givenProto); } -WebGPUChild* Instance::GetBridge() const { return mBridge; } - already_AddRefed Instance::RequestAdapter( const dom::GPURequestAdapterOptions& aOptions, ErrorResult& aRv) { RefPtr promise = dom::Promise::Create(mOwner, aRv); diff --git a/dom/webgpu/Instance.h b/dom/webgpu/Instance.h index a90285af930a..91e61cdb1885 100644 --- a/dom/webgpu/Instance.h +++ b/dom/webgpu/Instance.h @@ -27,22 +27,23 @@ class Instance final : public nsWrapperCache { GPU_DECL_CYCLE_COLLECTION(Instance) GPU_DECL_JS_WRAP(Instance) + nsIGlobalObject* GetParentObject() const { return mOwner; } + static already_AddRefed Create(nsIGlobalObject* aOwner); already_AddRefed RequestAdapter( const dom::GPURequestAdapterOptions& aOptions, ErrorResult& aRv); + const RefPtr mBridge; + private: explicit Instance(nsIGlobalObject* aOwner, WebGPUChild* aBridge); virtual ~Instance(); void Cleanup(); nsCOMPtr mOwner; - const RefPtr mBridge; public: - nsIGlobalObject* GetParentObject() const { return mOwner; } - WebGPUChild* GetBridge() const; }; } // namespace webgpu diff --git a/dom/webgpu/PipelineLayout.cpp b/dom/webgpu/PipelineLayout.cpp index 118e773ee681..f590702e5c28 100644 --- a/dom/webgpu/PipelineLayout.cpp +++ b/dom/webgpu/PipelineLayout.cpp @@ -14,7 +14,20 @@ namespace webgpu { GPU_IMPL_CYCLE_COLLECTION(PipelineLayout, mParent) GPU_IMPL_JS_WRAP(PipelineLayout) -PipelineLayout::~PipelineLayout() = default; +PipelineLayout::PipelineLayout(Device* const aParent, RawId aId) + : ChildOf(aParent), mId(aId) {} + +PipelineLayout::~PipelineLayout() { Cleanup(); } + +void PipelineLayout::Cleanup() { + if (mValid && mParent) { + mValid = false; + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyPipelineLayout(mId); + } + } +} } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/PipelineLayout.h b/dom/webgpu/PipelineLayout.h index e88dc3b11815..10746c32d6b6 100644 --- a/dom/webgpu/PipelineLayout.h +++ b/dom/webgpu/PipelineLayout.h @@ -8,6 +8,7 @@ #include "nsWrapperCache.h" #include "ObjectModel.h" +#include "mozilla/webgpu/WebGPUTypes.h" namespace mozilla { namespace webgpu { @@ -19,10 +20,13 @@ class PipelineLayout final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(PipelineLayout) GPU_DECL_JS_WRAP(PipelineLayout) + PipelineLayout(Device* const aParent, RawId aId); + + const RawId mId; + private: - PipelineLayout() = delete; virtual ~PipelineLayout(); - void Cleanup() {} + void Cleanup(); }; } // namespace webgpu diff --git a/dom/webgpu/ProgrammablePassEncoder.cpp b/dom/webgpu/ProgrammablePassEncoder.cpp index b8331aa8f7be..6811dc1de267 100644 --- a/dom/webgpu/ProgrammablePassEncoder.cpp +++ b/dom/webgpu/ProgrammablePassEncoder.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ProgrammablePassEncoder.h" +#include "BindGroup.h" namespace mozilla { namespace webgpu { diff --git a/dom/webgpu/ProgrammablePassEncoder.h b/dom/webgpu/ProgrammablePassEncoder.h index 5d28395060fb..5e78cb89cd2e 100644 --- a/dom/webgpu/ProgrammablePassEncoder.h +++ b/dom/webgpu/ProgrammablePassEncoder.h @@ -13,8 +13,6 @@ namespace mozilla { namespace dom { template class Sequence; -template -class Optional; } // namespace dom namespace webgpu { @@ -34,6 +32,12 @@ class ProgrammablePassEncoder : public nsISupports, public ObjectBase { protected: ~ProgrammablePassEncoder() = default; void Cleanup() {} + + public: + // TODO: remove all of this, see + // https://bugzilla.mozilla.org/show_bug.cgi?id=1611024 + virtual void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) = 0; }; } // namespace webgpu diff --git a/dom/webgpu/RenderBundleEncoder.cpp b/dom/webgpu/RenderBundleEncoder.cpp index 95f649a37db4..6a2679e87036 100644 --- a/dom/webgpu/RenderBundleEncoder.cpp +++ b/dom/webgpu/RenderBundleEncoder.cpp @@ -20,5 +20,13 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RenderBundleEncoder, NS_IMPL_CYCLE_COLLECTION_TRACE_END GPU_IMPL_JS_WRAP(RenderBundleEncoder) +void RenderBundleEncoder::SetBindGroup( + uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) { + if (mValid) { + MOZ_CRASH("TODO"); + } +} + } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/RenderBundleEncoder.h b/dom/webgpu/RenderBundleEncoder.h index 0944dce33920..1bf9118edf81 100644 --- a/dom/webgpu/RenderBundleEncoder.h +++ b/dom/webgpu/RenderBundleEncoder.h @@ -29,6 +29,8 @@ class RenderBundleEncoder final : public RenderEncoderBase, ~RenderBundleEncoder() = default; public: + void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) override; }; } // namespace webgpu diff --git a/dom/webgpu/RenderPassEncoder.cpp b/dom/webgpu/RenderPassEncoder.cpp index ed1aeb6d083d..24d3724644dd 100644 --- a/dom/webgpu/RenderPassEncoder.cpp +++ b/dom/webgpu/RenderPassEncoder.cpp @@ -21,5 +21,13 @@ GPU_IMPL_JS_WRAP(RenderPassEncoder) RenderPassEncoder::~RenderPassEncoder() = default; +void RenderPassEncoder::SetBindGroup( + uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) { + if (mValid) { + MOZ_CRASH("TODO"); + } +} + } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/RenderPassEncoder.h b/dom/webgpu/RenderPassEncoder.h index 38b5ef2c3af0..1530933a8443 100644 --- a/dom/webgpu/RenderPassEncoder.h +++ b/dom/webgpu/RenderPassEncoder.h @@ -39,6 +39,8 @@ class RenderPassEncoder final : public RenderEncoderBase, void Cleanup() {} public: + void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup, + const dom::Sequence& aDynamicOffsets) override; }; } // namespace webgpu diff --git a/dom/webgpu/Sampler.h b/dom/webgpu/Sampler.h index bf283ab20360..e54289ea9b19 100644 --- a/dom/webgpu/Sampler.h +++ b/dom/webgpu/Sampler.h @@ -19,6 +19,8 @@ class Sampler final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(Sampler) GPU_DECL_JS_WRAP(Sampler) + const RawId mId; + private: Sampler() = delete; virtual ~Sampler(); diff --git a/dom/webgpu/ShaderModule.cpp b/dom/webgpu/ShaderModule.cpp index 1b176968dba2..7c30e91a3f3a 100644 --- a/dom/webgpu/ShaderModule.cpp +++ b/dom/webgpu/ShaderModule.cpp @@ -14,7 +14,20 @@ namespace webgpu { GPU_IMPL_CYCLE_COLLECTION(ShaderModule, mParent) GPU_IMPL_JS_WRAP(ShaderModule) -ShaderModule::~ShaderModule() = default; +ShaderModule::ShaderModule(Device* const aParent, RawId aId) + : ChildOf(aParent), mId(aId) {} + +ShaderModule::~ShaderModule() { Cleanup(); } + +void ShaderModule::Cleanup() { + if (mValid && mParent) { + mValid = false; + WebGPUChild* bridge = mParent->mBridge; + if (bridge && bridge->IsOpen()) { + bridge->DestroyShaderModule(mId); + } + } +} } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/ShaderModule.h b/dom/webgpu/ShaderModule.h index 7af690d57f9d..d64fce322e57 100644 --- a/dom/webgpu/ShaderModule.h +++ b/dom/webgpu/ShaderModule.h @@ -19,10 +19,13 @@ class ShaderModule final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(ShaderModule) GPU_DECL_JS_WRAP(ShaderModule) + ShaderModule(Device* const aParent, RawId aId); + + const RawId mId; + private: - ShaderModule() = delete; virtual ~ShaderModule(); - void Cleanup() {} + void Cleanup(); }; } // namespace webgpu diff --git a/dom/webgpu/TextureView.h b/dom/webgpu/TextureView.h index db0fcc9f5d60..483830b9f647 100644 --- a/dom/webgpu/TextureView.h +++ b/dom/webgpu/TextureView.h @@ -19,6 +19,8 @@ class TextureView final : public ObjectBase, public ChildOf { GPU_DECL_CYCLE_COLLECTION(TextureView) GPU_DECL_JS_WRAP(TextureView) + const RawId mId; + private: TextureView() = delete; virtual ~TextureView(); diff --git a/dom/webgpu/ffi/moz.build b/dom/webgpu/ffi/moz.build index 985abd023ece..b290474e4565 100644 --- a/dom/webgpu/ffi/moz.build +++ b/dom/webgpu/ffi/moz.build @@ -15,7 +15,9 @@ if CONFIG['COMPILE_ENVIRONMENT']: GeneratedFile('wgpu_ffi_generated.h', script='/layout/style/RunCbindgen.py', entry_point='generate', - inputs=['/gfx/wgpu/wgpu-remote']) + inputs=[ + '/gfx/wgpu/wgpu-remote', + ]) EXPORTS.mozilla.webgpu.ffi += [ '!wgpu_ffi_generated.h', diff --git a/dom/webgpu/ipc/PWebGPU.ipdl b/dom/webgpu/ipc/PWebGPU.ipdl index bfe194c42519..aa64da9788f3 100644 --- a/dom/webgpu/ipc/PWebGPU.ipdl +++ b/dom/webgpu/ipc/PWebGPU.ipdl @@ -6,11 +6,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using RawId from "mozilla/webgpu/WebGPUTypes.h"; +using BufferAddress from "mozilla/webgpu/WebGPUTypes.h"; +using SerialBindGroupLayoutDescriptor from "mozilla/webgpu/WebGPUTypes.h"; +using SerialPipelineLayoutDescriptor from "mozilla/webgpu/WebGPUTypes.h"; +using SerialBindGroupDescriptor from "mozilla/webgpu/WebGPUTypes.h"; +using SerialComputePipelineDescriptor from "mozilla/webgpu/WebGPUTypes.h"; using dom::GPURequestAdapterOptions from "mozilla/dom/WebGPUBinding.h"; using dom::GPUDeviceDescriptor from "mozilla/dom/WebGPUBinding.h"; using dom::GPUBufferDescriptor from "mozilla/dom/WebGPUBinding.h"; using dom::GPUCommandEncoderDescriptor from "mozilla/dom/WebGPUBinding.h"; using dom::GPUCommandBufferDescriptor from "mozilla/dom/WebGPUBinding.h"; +using dom::GPUPipelineLayoutDescriptor from "mozilla/dom/WebGPUBinding.h"; include "mozilla/webgpu/WebGPUSerialize.h"; include protocol PCompositorBridge; @@ -37,11 +43,22 @@ parent: async BufferMapRead(RawId selfId, Shmem shmem) returns (Shmem sm); async BufferDestroy(RawId selfId); async DeviceCreateCommandEncoder(RawId selfId, GPUCommandEncoderDescriptor desc, RawId newId); + async CommandEncoderCopyBufferToBuffer(RawId selfId, RawId sourceId, BufferAddress sourceOffset, RawId destinationId, BufferAddress destinationOffset, BufferAddress size); async CommandEncoderRunComputePass(RawId selfId, Shmem shmem); async CommandEncoderFinish(RawId selfId, GPUCommandBufferDescriptor desc); async CommandEncoderDestroy(RawId selfId); async CommandBufferDestroy(RawId selfId); async QueueSubmit(RawId selfId, RawId[] commandBuffers); + async DeviceCreateBindGroupLayout(RawId selfId, SerialBindGroupLayoutDescriptor desc, RawId newId); + async BindGroupLayoutDestroy(RawId selfId); + async DeviceCreatePipelineLayout(RawId selfId, SerialPipelineLayoutDescriptor desc, RawId newId); + async PipelineLayoutDestroy(RawId selfId); + async DeviceCreateBindGroup(RawId selfId, SerialBindGroupDescriptor desc, RawId newId); + async BindGroupDestroy(RawId selfId); + async DeviceCreateShaderModule(RawId selfId, uint32_t[] data, RawId newId); + async ShaderModuleDestroy(RawId selfId); + async DeviceCreateComputePipeline(RawId selfId, SerialComputePipelineDescriptor desc, RawId newId); + async ComputePipelineDestroy(RawId selfId); async Shutdown(); child: diff --git a/dom/webgpu/ipc/WebGPUChild.cpp b/dom/webgpu/ipc/WebGPUChild.cpp index 7d3cb98d5399..f931a942d86b 100644 --- a/dom/webgpu/ipc/WebGPUChild.cpp +++ b/dom/webgpu/ipc/WebGPUChild.cpp @@ -110,6 +110,100 @@ RawId WebGPUChild::CommandEncoderFinish( return aSelfId; } +RawId WebGPUChild::DeviceCreateBindGroupLayout( + RawId aSelfId, const dom::GPUBindGroupLayoutDescriptor& aDesc) { + RawId id = ffi::wgpu_client_make_bind_group_layout_id(mClient, aSelfId); + nsTArray bindings(aDesc.mBindings.Length()); + for (const auto& binding : aDesc.mBindings) { + ffi::WGPUBindGroupLayoutBinding b = {}; + b.binding = binding.mBinding; + b.visibility = binding.mVisibility; + b.ty = ffi::WGPUBindingType(binding.mType); + Unused << binding.mTextureComponentType; // TODO + b.texture_dimension = + ffi::WGPUTextureViewDimension(binding.mTextureDimension); + b.multisampled = binding.mMultisampled; + b.dynamic = binding.mDynamic; + bindings.AppendElement(b); + } + SerialBindGroupLayoutDescriptor desc = {std::move(bindings)}; + if (!SendDeviceCreateBindGroupLayout(aSelfId, desc, id)) { + MOZ_CRASH("IPC failure"); + } + return id; +} + +RawId WebGPUChild::DeviceCreatePipelineLayout( + RawId aSelfId, const dom::GPUPipelineLayoutDescriptor& aDesc) { + RawId id = ffi::wgpu_client_make_pipeline_layout_id(mClient, aSelfId); + SerialPipelineLayoutDescriptor desc = {}; + for (const auto& layouts : aDesc.mBindGroupLayouts) { + desc.mBindGroupLayouts.AppendElement(layouts->mId); + } + if (!SendDeviceCreatePipelineLayout(aSelfId, desc, id)) { + MOZ_CRASH("IPC failure"); + } + return id; +} + +RawId WebGPUChild::DeviceCreateBindGroup( + RawId aSelfId, const dom::GPUBindGroupDescriptor& aDesc) { + RawId id = ffi::wgpu_client_make_bind_group_id(mClient, aSelfId); + SerialBindGroupDescriptor desc = {}; + desc.mLayout = aDesc.mLayout->mId; + for (const auto& binding : aDesc.mBindings) { + SerialBindGroupBinding bd = {}; + bd.mBinding = binding.mBinding; + if (binding.mResource.IsGPUBufferBinding()) { + bd.mType = SerialBindGroupBindingType::Buffer; + const auto& bufBinding = binding.mResource.GetAsGPUBufferBinding(); + bd.mValue = bufBinding.mBuffer->mId; + bd.mBufferOffset = bufBinding.mOffset; + bd.mBufferSize = + bufBinding.mSize.WasPassed() ? bufBinding.mSize.Value() : 0; + } + if (binding.mResource.IsGPUTextureView()) { + bd.mType = SerialBindGroupBindingType::Texture; + bd.mValue = binding.mResource.GetAsGPUTextureView()->mId; + } + if (binding.mResource.IsGPUSampler()) { + bd.mType = SerialBindGroupBindingType::Sampler; + bd.mValue = binding.mResource.GetAsGPUSampler()->mId; + } + desc.mBindings.AppendElement(bd); + } + if (!SendDeviceCreateBindGroup(aSelfId, desc, id)) { + MOZ_CRASH("IPC failure"); + } + return id; +} + +RawId WebGPUChild::DeviceCreateShaderModule( + RawId aSelfId, const dom::GPUShaderModuleDescriptor& aDesc) { + RawId id = ffi::wgpu_client_make_shader_module_id(mClient, aSelfId); + MOZ_ASSERT(aDesc.mCode.IsUint32Array()); + const auto& code = aDesc.mCode.GetAsUint32Array(); + code.ComputeLengthAndData(); + nsTArray data(code.Length()); + data.AppendElements(code.Data(), code.Length()); + if (!SendDeviceCreateShaderModule(aSelfId, data, id)) { + MOZ_CRASH("IPC failure"); + } + return id; +} +RawId WebGPUChild::DeviceCreateComputePipeline( + RawId aSelfId, const dom::GPUComputePipelineDescriptor& aDesc) { + RawId id = ffi::wgpu_client_make_compute_pipeline_id(mClient, aSelfId); + SerialProgrammableStageDescriptor stage = {}; + stage.mModule = aDesc.mComputeStage.mModule->mId; + stage.mEntryPoint = aDesc.mComputeStage.mEntryPoint; + SerialComputePipelineDescriptor desc = {aDesc.mLayout->mId, stage}; + if (!SendDeviceCreateComputePipeline(aSelfId, desc, id)) { + MOZ_CRASH("IPC failure"); + } + return id; +} + void WebGPUChild::QueueSubmit(RawId aSelfId, const nsTArray& aCommandBufferIds) { SendQueueSubmit(aSelfId, aCommandBufferIds); @@ -134,6 +228,26 @@ void WebGPUChild::DestroyCommandBuffer(RawId aId) { SendCommandBufferDestroy(aId); ffi::wgpu_client_kill_encoder_id(mClient, aId); } +void WebGPUChild::DestroyBindGroupLayout(RawId aId) { + SendBindGroupLayoutDestroy(aId); + ffi::wgpu_client_kill_bind_group_layout_id(mClient, aId); +} +void WebGPUChild::DestroyPipelineLayout(RawId aId) { + SendPipelineLayoutDestroy(aId); + ffi::wgpu_client_kill_pipeline_layout_id(mClient, aId); +} +void WebGPUChild::DestroyBindGroup(RawId aId) { + SendBindGroupDestroy(aId); + ffi::wgpu_client_kill_bind_group_id(mClient, aId); +} +void WebGPUChild::DestroyShaderModule(RawId aId) { + SendShaderModuleDestroy(aId); + ffi::wgpu_client_kill_shader_module_id(mClient, aId); +} +void WebGPUChild::DestroyComputePipeline(RawId aId) { + SendComputePipelineDestroy(aId); + ffi::wgpu_client_kill_compute_pipeline_id(mClient, aId); +} } // namespace webgpu } // namespace mozilla diff --git a/dom/webgpu/ipc/WebGPUChild.h b/dom/webgpu/ipc/WebGPUChild.h index d76843febc70..5ad9593c4183 100644 --- a/dom/webgpu/ipc/WebGPUChild.h +++ b/dom/webgpu/ipc/WebGPUChild.h @@ -44,12 +44,28 @@ class WebGPUChild final : public PWebGPUChild { RawId aSelfId, const dom::GPUCommandEncoderDescriptor& aDesc); RawId CommandEncoderFinish(RawId aSelfId, const dom::GPUCommandBufferDescriptor& aDesc); + RawId DeviceCreateBindGroupLayout( + RawId aSelfId, const dom::GPUBindGroupLayoutDescriptor& aDesc); + RawId DeviceCreatePipelineLayout( + RawId aSelfId, const dom::GPUPipelineLayoutDescriptor& aDesc); + RawId DeviceCreateBindGroup(RawId aSelfId, + const dom::GPUBindGroupDescriptor& aDesc); + RawId DeviceCreateShaderModule(RawId aSelfId, + const dom::GPUShaderModuleDescriptor& aDesc); + RawId DeviceCreateComputePipeline( + RawId aSelfId, const dom::GPUComputePipelineDescriptor& aDesc); + void QueueSubmit(RawId aSelfId, const nsTArray& aCommandBufferIds); void DestroyAdapter(RawId aId); void DestroyBuffer(RawId aId); void DestroyCommandEncoder(RawId aId); void DestroyCommandBuffer(RawId aId); + void DestroyBindGroupLayout(RawId aId); + void DestroyPipelineLayout(RawId aId); + void DestroyBindGroup(RawId aId); + void DestroyShaderModule(RawId aId); + void DestroyComputePipeline(RawId aId); private: virtual ~WebGPUChild(); diff --git a/dom/webgpu/ipc/WebGPUParent.cpp b/dom/webgpu/ipc/WebGPUParent.cpp index 265d8fd6953b..6f964c7447a8 100644 --- a/dom/webgpu/ipc/WebGPUParent.cpp +++ b/dom/webgpu/ipc/WebGPUParent.cpp @@ -46,6 +46,9 @@ ipc::IPCResult WebGPUParent::RecvInstanceRequestAdapter( ipc::IPCResult WebGPUParent::RecvAdapterRequestDevice( RawId aSelfId, const dom::GPUDeviceDescriptor& aDesc, RawId aNewId) { ffi::WGPUDeviceDescriptor desc = {}; + desc.limits.max_bind_groups = aDesc.mLimits.WasPassed() + ? aDesc.mLimits.Value().mMaxBindGroups + : WGPUDEFAULT_BIND_GROUPS; Unused << aDesc; // no useful fields // TODO: fill up the descriptor ffi::wgpu_server_adapter_request_device(mContext, aSelfId, &desc, aNewId); @@ -67,6 +70,11 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateBuffer( ffi::WGPUBufferDescriptor desc = {}; desc.usage = aDesc.mUsage; desc.size = aDesc.mSize; + // tweak: imply STORAGE_READ. This is yet to be figured out by the spec, + // see https://github.com/gpuweb/gpuweb/issues/541 + if (desc.usage & WGPUBufferUsage_STORAGE) { + desc.usage |= WGPUBufferUsage_STORAGE_READ; + } ffi::wgpu_server_device_create_buffer(mContext, aSelfId, &desc, aNewId); return IPC_OK(); } @@ -121,6 +129,16 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateCommandEncoder( return IPC_OK(); } +ipc::IPCResult WebGPUParent::RecvCommandEncoderCopyBufferToBuffer( + RawId aSelfId, RawId aSourceId, BufferAddress aSourceOffset, + RawId aDestinationId, BufferAddress aDestinationOffset, + BufferAddress aSize) { + ffi::wgpu_server_encoder_copy_buffer_to_buffer(mContext, aSelfId, aSourceId, + aSourceOffset, aDestinationId, + aDestinationOffset, aSize); + return IPC_OK(); +} + ipc::IPCResult WebGPUParent::RecvCommandEncoderRunComputePass(RawId aSelfId, Shmem&& shmem) { ffi::wgpu_server_encode_compute_pass(mContext, aSelfId, shmem.get(), @@ -153,6 +171,107 @@ ipc::IPCResult WebGPUParent::RecvQueueSubmit( return IPC_OK(); } +ipc::IPCResult WebGPUParent::RecvDeviceCreateBindGroupLayout( + RawId aSelfId, const SerialBindGroupLayoutDescriptor& aDesc, RawId aNewId) { + ffi::WGPUBindGroupLayoutDescriptor desc = {}; + desc.bindings = aDesc.mBindings.Elements(); + desc.bindings_length = aDesc.mBindings.Length(); + ffi::wgpu_server_device_create_bind_group_layout(mContext, aSelfId, &desc, + aNewId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvBindGroupLayoutDestroy(RawId aSelfId) { + ffi::wgpu_server_bind_group_layout_destroy(mContext, aSelfId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvDeviceCreatePipelineLayout( + RawId aSelfId, const SerialPipelineLayoutDescriptor& aDesc, RawId aNewId) { + ffi::WGPUPipelineLayoutDescriptor desc = {}; + desc.bind_group_layouts = aDesc.mBindGroupLayouts.Elements(); + desc.bind_group_layouts_length = aDesc.mBindGroupLayouts.Length(); + ffi::wgpu_server_device_create_pipeline_layout(mContext, aSelfId, &desc, + aNewId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvPipelineLayoutDestroy(RawId aSelfId) { + ffi::wgpu_server_pipeline_layout_destroy(mContext, aSelfId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvDeviceCreateBindGroup( + RawId aSelfId, const SerialBindGroupDescriptor& aDesc, RawId aNewId) { + nsTArray ffiBindings(aDesc.mBindings.Length()); + for (const auto& binding : aDesc.mBindings) { + ffi::WGPUBindGroupBinding bgb = {}; + bgb.binding = binding.mBinding; + switch (binding.mType) { + case SerialBindGroupBindingType::Buffer: + bgb.resource.tag = ffi::WGPUBindingResource_Buffer; + bgb.resource.buffer._0.buffer = binding.mValue; + bgb.resource.buffer._0.offset = binding.mBufferOffset; + bgb.resource.buffer._0.size = binding.mBufferSize; + break; + case SerialBindGroupBindingType::Texture: + bgb.resource.tag = ffi::WGPUBindingResource_TextureView; + bgb.resource.texture_view._0 = binding.mValue; + break; + case SerialBindGroupBindingType::Sampler: + bgb.resource.tag = ffi::WGPUBindingResource_Sampler; + bgb.resource.sampler._0 = binding.mValue; + break; + default: + MOZ_CRASH("unreachable"); + } + ffiBindings.AppendElement(bgb); + } + ffi::WGPUBindGroupDescriptor desc = {}; + desc.layout = aDesc.mLayout; + desc.bindings = ffiBindings.Elements(); + desc.bindings_length = ffiBindings.Length(); + ffi::wgpu_server_device_create_bind_group(mContext, aSelfId, &desc, aNewId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvBindGroupDestroy(RawId aSelfId) { + ffi::wgpu_server_bind_group_destroy(mContext, aSelfId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvDeviceCreateShaderModule( + RawId aSelfId, const nsTArray& aData, RawId aNewId) { + ffi::WGPUShaderModuleDescriptor desc = {}; + desc.code.bytes = aData.Elements(); + desc.code.length = aData.Length(); + ffi::wgpu_server_device_create_shader_module(mContext, aSelfId, &desc, + aNewId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvShaderModuleDestroy(RawId aSelfId) { + ffi::wgpu_server_shader_module_destroy(mContext, aSelfId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvDeviceCreateComputePipeline( + RawId aSelfId, const SerialComputePipelineDescriptor& aDesc, RawId aNewId) { + NS_LossyConvertUTF16toASCII entryPoint(aDesc.mComputeStage.mEntryPoint); + ffi::WGPUComputePipelineDescriptor desc = {}; + desc.layout = aDesc.mLayout; + desc.compute_stage.module = aDesc.mComputeStage.mModule; + desc.compute_stage.entry_point = entryPoint.get(); + ffi::wgpu_server_device_create_compute_pipeline(mContext, aSelfId, &desc, + aNewId); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvComputePipelineDestroy(RawId aSelfId) { + ffi::wgpu_server_compute_pipeline_destroy(mContext, aSelfId); + return IPC_OK(); +} + ipc::IPCResult WebGPUParent::RecvShutdown() { mTimer.Stop(); ffi::wgpu_server_poll_all_devices(mContext, true); diff --git a/dom/webgpu/ipc/WebGPUParent.h b/dom/webgpu/ipc/WebGPUParent.h index d1eb3a7630a9..9637c57a9e7d 100644 --- a/dom/webgpu/ipc/WebGPUParent.h +++ b/dom/webgpu/ipc/WebGPUParent.h @@ -42,6 +42,10 @@ class WebGPUParent final : public PWebGPUParent { ipc::IPCResult RecvDeviceCreateCommandEncoder( RawId aSelfId, const dom::GPUCommandEncoderDescriptor& aDesc, RawId aNewId); + ipc::IPCResult RecvCommandEncoderCopyBufferToBuffer( + RawId aSelfId, RawId aSourceId, BufferAddress aSourceOffset, + RawId aDestinationId, BufferAddress aDestinationOffset, + BufferAddress aSize); ipc::IPCResult RecvCommandEncoderRunComputePass(RawId aSelfId, Shmem&& shmem); ipc::IPCResult RecvCommandEncoderFinish( RawId aSelfId, const dom::GPUCommandBufferDescriptor& aDesc); @@ -49,6 +53,24 @@ class WebGPUParent final : public PWebGPUParent { ipc::IPCResult RecvCommandBufferDestroy(RawId aSelfId); ipc::IPCResult RecvQueueSubmit(RawId aSelfId, const nsTArray& aCommandBuffers); + ipc::IPCResult RecvDeviceCreateBindGroupLayout( + RawId aSelfId, const SerialBindGroupLayoutDescriptor& aDesc, + RawId aNewId); + ipc::IPCResult RecvBindGroupLayoutDestroy(RawId aSelfId); + ipc::IPCResult RecvDeviceCreatePipelineLayout( + RawId aSelfId, const SerialPipelineLayoutDescriptor& aDesc, RawId aNewId); + ipc::IPCResult RecvPipelineLayoutDestroy(RawId aSelfId); + ipc::IPCResult RecvDeviceCreateBindGroup( + RawId aSelfId, const SerialBindGroupDescriptor& aDesc, RawId aNewId); + ipc::IPCResult RecvBindGroupDestroy(RawId aSelfId); + ipc::IPCResult RecvDeviceCreateShaderModule(RawId aSelfId, + const nsTArray& aData, + RawId aNewId); + ipc::IPCResult RecvShaderModuleDestroy(RawId aSelfId); + ipc::IPCResult RecvDeviceCreateComputePipeline( + RawId aSelfId, const SerialComputePipelineDescriptor& aDesc, + RawId aNewId); + ipc::IPCResult RecvComputePipelineDestroy(RawId aSelfId); ipc::IPCResult RecvShutdown(); private: diff --git a/dom/webgpu/ipc/WebGPUSerialize.h b/dom/webgpu/ipc/WebGPUSerialize.h index 54c33b6024b1..9ab173093741 100644 --- a/dom/webgpu/ipc/WebGPUSerialize.h +++ b/dom/webgpu/ipc/WebGPUSerialize.h @@ -9,14 +9,17 @@ #include "WebGPUTypes.h" #include "ipc/IPCMessageUtils.h" #include "mozilla/dom/WebGPUBinding.h" +#include "mozilla/webgpu/ffi/wgpu.h" namespace IPC { -#define DEFINE_IPC_SERIALIZER_ENUM(something) \ - template <> \ - struct ParamTraits \ - : public ContiguousEnumSerializer {} +#define DEFINE_IPC_SERIALIZER_ENUM_GUARD(something, guard) \ + template <> \ + struct ParamTraits \ + : public ContiguousEnumSerializer {} + +#define DEFINE_IPC_SERIALIZER_ENUM(something) \ + DEFINE_IPC_SERIALIZER_ENUM_GUARD(something, something::EndGuard_) DEFINE_IPC_SERIALIZER_ENUM(mozilla::dom::GPUPowerPreference); @@ -32,7 +35,35 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::GPUBufferDescriptor, mSize, DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(mozilla::dom::GPUCommandEncoderDescriptor); DEFINE_IPC_SERIALIZER_WITHOUT_FIELDS(mozilla::dom::GPUCommandBufferDescriptor); +// TODO: have the enum sentinels generated by `cbindgen` when it supports them +// see https://github.com/eqrion/cbindgen/issues/458 +DEFINE_IPC_SERIALIZER_ENUM_GUARD( + mozilla::webgpu::ffi::WGPUBindingType, + mozilla::webgpu::ffi::WGPUBindingType_StorageTexture); +DEFINE_IPC_SERIALIZER_ENUM_GUARD( + mozilla::webgpu::ffi::WGPUTextureViewDimension, + mozilla::webgpu::ffi::WGPUTextureViewDimension_D3); +DEFINE_IPC_SERIALIZER_WITH_FIELDS( + mozilla::webgpu::ffi::WGPUBindGroupLayoutBinding, binding, visibility, ty, + texture_dimension, multisampled, dynamic); +DEFINE_IPC_SERIALIZER_WITH_FIELDS( + mozilla::webgpu::SerialBindGroupLayoutDescriptor, mBindings); +DEFINE_IPC_SERIALIZER_WITH_FIELDS( + mozilla::webgpu::SerialPipelineLayoutDescriptor, mBindGroupLayouts); +DEFINE_IPC_SERIALIZER_ENUM(mozilla::webgpu::SerialBindGroupBindingType); +DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::SerialBindGroupBinding, + mBinding, mType, mValue, mBufferOffset, + mBufferSize); +DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::SerialBindGroupDescriptor, + mLayout, mBindings); + +DEFINE_IPC_SERIALIZER_WITH_FIELDS( + mozilla::webgpu::SerialProgrammableStageDescriptor, mModule, mEntryPoint); +DEFINE_IPC_SERIALIZER_WITH_FIELDS( + mozilla::webgpu::SerialComputePipelineDescriptor, mLayout, mComputeStage); + #undef DEFINE_IPC_SERIALIZER_ENUM +#undef DEFINE_IPC_SERIALIZER_ENUM_GUARD } // namespace IPC #endif // WEBGPU_SERIALIZE_H_ diff --git a/dom/webgpu/ipc/WebGPUTypes.h b/dom/webgpu/ipc/WebGPUTypes.h index b253fcc2af4f..6d221642e562 100644 --- a/dom/webgpu/ipc/WebGPUTypes.h +++ b/dom/webgpu/ipc/WebGPUTypes.h @@ -7,15 +7,56 @@ #define WEBGPU_TYPES_H_ #include +#include "nsTArray.h" namespace mozilla { namespace webgpu { +namespace ffi { +struct WGPUBindGroupLayoutBinding; +} // namespace ffi typedef uint64_t RawId; typedef uint64_t BufferAddress; -} // namespace webgpu +struct SerialBindGroupLayoutDescriptor { + nsTArray mBindings; +}; +struct SerialPipelineLayoutDescriptor { + nsTArray mBindGroupLayouts; +}; + +enum class SerialBindGroupBindingType : uint8_t { + Buffer, + Texture, + Sampler, + EndGuard_ +}; + +struct SerialBindGroupBinding { + uint32_t mBinding; + SerialBindGroupBindingType mType; + RawId mValue; + BufferAddress mBufferOffset; + BufferAddress mBufferSize; +}; + +struct SerialBindGroupDescriptor { + RawId mLayout; + nsTArray mBindings; +}; + +struct SerialProgrammableStageDescriptor { + RawId mModule; + nsString mEntryPoint; +}; + +struct SerialComputePipelineDescriptor { + RawId mLayout; + SerialProgrammableStageDescriptor mComputeStage; +}; + +} // namespace webgpu } // namespace mozilla #endif // WEBGPU_TYPES_H_ diff --git a/dom/webidl/WebGPU.webidl b/dom/webidl/WebGPU.webidl index e296b3a0831c..6d6f1c7fb262 100644 --- a/dom/webidl/WebGPU.webidl +++ b/dom/webidl/WebGPU.webidl @@ -115,12 +115,12 @@ interface GPUDevice { //GPUTexture createTexture(GPUTextureDescriptor descriptor); //GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {}); - //GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); - //GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); - //GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); + GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); + GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); + GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); - //GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); - //GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); + GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); + GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); //GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); [NewObject] @@ -634,7 +634,7 @@ dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { }; dictionary GPUProgrammableStageDescriptor { - required GPUShaderModule module_; + required GPUShaderModule module; required DOMString entryPoint; }; @@ -764,7 +764,6 @@ interface GPUCommandEncoder { [NewObject] GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {}); - /* void copyBufferToBuffer( GPUBuffer source, u64 sourceOffset, @@ -772,6 +771,7 @@ interface GPUCommandEncoder { u64 destinationOffset, u64 size); + /* void copyBufferToTexture( GPUBufferCopyView source, GPUTextureCopyView destination, @@ -805,8 +805,8 @@ GPUCommandEncoder includes GPUObjectBase; [Pref="dom.webgpu.enabled", Exposed=Window] interface GPUProgrammablePassEncoder { - //void setBindGroup(u32 index, GPUBindGroup bindGroup, - // optional sequence dynamicOffsets); + void setBindGroup(unsigned long index, GPUBindGroup bindGroup, + optional sequence dynamicOffsets = []); //void pushDebugGroup(DOMString groupLabel); //void popDebugGroup(); @@ -856,7 +856,7 @@ dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase { [Pref="dom.webgpu.enabled", Exposed=Window] interface GPUComputePassEncoder : GPUProgrammablePassEncoder { - //void setPipeline(GPUComputePipeline pipeline); + void setPipeline(GPUComputePipeline pipeline); void dispatch(u32 x, optional u32 y = 1, optional u32 z = 1); //void dispatchIndirect(GPUBuffer indirectBuffer, u64 indirectOffset); diff --git a/gfx/wgpu/ffi/wgpu.h b/gfx/wgpu/ffi/wgpu.h index 56ef02c1c7a7..521c9f3cf45b 100644 --- a/gfx/wgpu/ffi/wgpu.h +++ b/gfx/wgpu/ffi/wgpu.h @@ -413,6 +413,8 @@ typedef WGPURawPass *WGPUComputePassId; typedef const char *WGPURawString; +typedef uint32_t WGPUDynamicOffset; + typedef uint64_t WGPUId_ComputePipeline_Dummy; typedef WGPUId_ComputePipeline_Dummy WGPUComputePipelineId; @@ -502,8 +504,8 @@ typedef uint32_t WGPUBufferUsage; #define WGPUBufferUsage_VERTEX 32 #define WGPUBufferUsage_UNIFORM 64 #define WGPUBufferUsage_STORAGE 128 -#define WGPUBufferUsage_STORAGE_READ 256 -#define WGPUBufferUsage_INDIRECT 512 +#define WGPUBufferUsage_INDIRECT 256 +#define WGPUBufferUsage_STORAGE_READ 512 #define WGPUBufferUsage_NONE 0 typedef struct { @@ -788,7 +790,7 @@ void wgpu_compute_pass_push_debug_group(WGPURawPass *_pass, WGPURawString _label void wgpu_compute_pass_set_bind_group(WGPURawPass *pass, uint32_t index, WGPUBindGroupId bind_group_id, - const WGPUBufferAddress *offsets, + const WGPUDynamicOffset *offsets, uintptr_t offset_length); void wgpu_compute_pass_set_pipeline(WGPURawPass *pass, WGPUComputePipelineId pipeline_id); @@ -888,7 +890,7 @@ void wgpu_render_pass_push_debug_group(WGPURawRenderPass *_pass, WGPURawString _ void wgpu_render_pass_set_bind_group(WGPURawRenderPass *pass, uint32_t index, WGPUBindGroupId bind_group_id, - const WGPUBufferAddress *offsets, + const WGPUDynamicOffset *offsets, uintptr_t offset_length); void wgpu_render_pass_set_blend_color(WGPURawRenderPass *pass, const WGPUColor *color); diff --git a/gfx/wgpu/wgpu-core/src/command/bind.rs b/gfx/wgpu/wgpu-core/src/command/bind.rs index 443d034a24b8..33737ccff684 100644 --- a/gfx/wgpu/wgpu-core/src/command/bind.rs +++ b/gfx/wgpu/wgpu-core/src/command/bind.rs @@ -6,7 +6,7 @@ use crate::{ binding_model::BindGroup, hub::GfxBackend, id::{BindGroupId, BindGroupLayoutId, PipelineLayoutId}, - BufferAddress, + DynamicOffset, Stored, }; @@ -26,7 +26,7 @@ pub struct BindGroupPair { #[derive(Debug)] pub enum LayoutChange<'a> { Unchanged, - Match(BindGroupId, &'a [BufferAddress]), + Match(BindGroupId, &'a [DynamicOffset]), Mismatch, } @@ -41,7 +41,7 @@ pub struct FollowUpIter<'a> { iter: slice::Iter<'a, BindGroupEntry>, } impl<'a> Iterator for FollowUpIter<'a> { - type Item = (BindGroupId, &'a [BufferAddress]); + type Item = (BindGroupId, &'a [DynamicOffset]); fn next(&mut self) -> Option { self.iter .next() @@ -58,7 +58,7 @@ impl<'a> Iterator for FollowUpIter<'a> { pub struct BindGroupEntry { expected_layout_id: Option, provided: Option, - dynamic_offsets: Vec, + dynamic_offsets: Vec, } impl BindGroupEntry { @@ -66,7 +66,7 @@ impl BindGroupEntry { &mut self, bind_group_id: BindGroupId, bind_group: &BindGroup, - offsets: &[BufferAddress], + offsets: &[DynamicOffset], ) -> Provision { debug_assert_eq!(B::VARIANT, bind_group_id.backend()); @@ -167,7 +167,7 @@ impl Binder { index: usize, bind_group_id: BindGroupId, bind_group: &BindGroup, - offsets: &[BufferAddress], + offsets: &[DynamicOffset], ) -> Option<(PipelineLayoutId, FollowUpIter<'a>)> { log::trace!("\tBinding [{}] = group {:?}", index, bind_group_id); debug_assert_eq!(B::VARIANT, bind_group_id.backend()); diff --git a/gfx/wgpu/wgpu-core/src/command/compute.rs b/gfx/wgpu/wgpu-core/src/command/compute.rs index b8575370d7a9..0372884c807b 100644 --- a/gfx/wgpu/wgpu-core/src/command/compute.rs +++ b/gfx/wgpu/wgpu-core/src/command/compute.rs @@ -13,6 +13,7 @@ use crate::{ id, resource::BufferUsage, BufferAddress, + DynamicOffset, }; use hal::command::CommandBuffer as _; @@ -27,7 +28,7 @@ enum ComputeCommand { index: u8, num_dynamic_offsets: u8, bind_group_id: id::BindGroupId, - phantom_offsets: PhantomSlice, + phantom_offsets: PhantomSlice, }, SetPipeline(id::ComputePipelineId), Dispatch([u32; 3]), @@ -95,7 +96,7 @@ impl Global { if cfg!(debug_assertions) { for off in offsets { assert_eq!( - *off % BIND_BUFFER_ALIGNMENT, + *off as BufferAddress % BIND_BUFFER_ALIGNMENT, 0, "Misaligned dynamic buffer offset: {} does not align with {}", off, @@ -222,6 +223,7 @@ pub mod compute_ffi { use crate::{ id, BufferAddress, + DynamicOffset, RawString, }; use std::{convert::TryInto, slice}; @@ -231,7 +233,7 @@ pub mod compute_ffi { pass: &mut RawPass, index: u32, bind_group_id: id::BindGroupId, - offsets: *const BufferAddress, + offsets: *const DynamicOffset, offset_length: usize, ) { pass.encode(&ComputeCommand::SetBindGroup { diff --git a/gfx/wgpu/wgpu-core/src/command/render.rs b/gfx/wgpu/wgpu-core/src/command/render.rs index f71bc62035a8..fa2e58b35fce 100644 --- a/gfx/wgpu/wgpu-core/src/command/render.rs +++ b/gfx/wgpu/wgpu-core/src/command/render.rs @@ -24,6 +24,7 @@ use crate::{ track::TrackerSet, BufferAddress, Color, + DynamicOffset, Stored, }; @@ -106,7 +107,7 @@ enum RenderCommand { index: u8, num_dynamic_offsets: u8, bind_group_id: id::BindGroupId, - phantom_offsets: PhantomSlice, + phantom_offsets: PhantomSlice, }, SetPipeline(id::RenderPipelineId), SetIndexBuffer { @@ -798,7 +799,7 @@ impl Global { if cfg!(debug_assertions) { for off in offsets { assert_eq!( - *off % BIND_BUFFER_ALIGNMENT, + *off as BufferAddress % BIND_BUFFER_ALIGNMENT, 0, "Misaligned dynamic buffer offset: {} does not align with {}", off, @@ -1124,6 +1125,7 @@ pub mod render_ffi { id, BufferAddress, Color, + DynamicOffset, RawString, }; use std::{convert::TryInto, slice}; @@ -1133,7 +1135,7 @@ pub mod render_ffi { pass: &mut RawRenderPass, index: u32, bind_group_id: id::BindGroupId, - offsets: *const BufferAddress, + offsets: *const DynamicOffset, offset_length: usize, ) { pass.raw.encode(&RenderCommand::SetBindGroup { diff --git a/gfx/wgpu/wgpu-core/src/device/mod.rs b/gfx/wgpu/wgpu-core/src/device/mod.rs index d412e89c6b75..3409e6b49f65 100644 --- a/gfx/wgpu/wgpu-core/src/device/mod.rs +++ b/gfx/wgpu/wgpu-core/src/device/mod.rs @@ -498,6 +498,8 @@ impl> Global { let hub = B::hub(self); let mut token = Token::root(); + log::info!("Create buffer {:?} with ID {:?}", desc, id_in); + let (device_guard, mut token) = hub.devices.read(&mut token); let device = &device_guard[device_id]; let buffer = device.create_buffer(device_id, desc); @@ -884,14 +886,16 @@ impl> Global { .map(|b| (b.binding, b)) .collect(); - { - let (bind_group_layout_guard, _) = hub.bind_group_layouts.read(&mut token); - let bind_group_layout = - bind_group_layout_guard - .iter(device_id.backend()) - .find(|(_, bgl)| bgl.bindings == bindings_map); + // TODO: deduplicate the bind group layouts at some level. + // We can't do it right here, because in the remote scenario + // the client need to know if the same ID can be used, or not. + if false { + let (bgl_guard, _) = hub.bind_group_layouts.read(&mut token); + let bind_group_layout_id = bgl_guard + .iter(device_id.backend()) + .find(|(_, bgl)| bgl.bindings == bindings_map); - if let Some((id, _)) = bind_group_layout { + if let Some((id, _)) = bind_group_layout_id { return id; } } @@ -925,6 +929,13 @@ impl> Global { hub.bind_group_layouts .register_identity(id_in, layout, &mut token) } + + pub fn bind_group_layout_destroy(&self, bind_group_layout_id: id::BindGroupLayoutId) { + let hub = B::hub(self); + let mut token = Token::root(); + //TODO: track usage by GPU + hub.bind_group_layouts.unregister(bind_group_layout_id, &mut token); + } } impl> Global { @@ -967,6 +978,13 @@ impl> Global { hub.pipeline_layouts .register_identity(id_in, layout, &mut token) } + + pub fn pipeline_layout_destroy(&self, pipeline_layout_id: id::PipelineLayoutId) { + let hub = B::hub(self); + let mut token = Token::root(); + //TODO: track usage by GPU + hub.pipeline_layouts.unregister(pipeline_layout_id, &mut token); + } } impl> Global { @@ -1200,6 +1218,13 @@ impl> Global { hub.shader_modules .register_identity(id_in, shader, &mut token) } + + pub fn shader_module_destroy(&self, shader_module_id: id::ShaderModuleId) { + let hub = B::hub(self); + let mut token = Token::root(); + //TODO: track usage by GPU + hub.shader_modules.unregister(shader_module_id, &mut token); + } } impl> Global { @@ -1718,6 +1743,13 @@ impl> Global { hub.render_pipelines .register_identity(id_in, pipeline, &mut token) } + + pub fn render_pipeline_destroy(&self, render_pipeline_id: id::RenderPipelineId) { + let hub = B::hub(self); + let mut token = Token::root(); + //TODO: track usage by GPU + hub.render_pipelines.unregister(render_pipeline_id, &mut token); + } } impl> Global { @@ -1773,6 +1805,13 @@ impl> Global { hub.compute_pipelines .register_identity(id_in, pipeline, &mut token) } + + pub fn compute_pipeline_destroy(&self, compute_pipeline_id: id::ComputePipelineId) { + let hub = B::hub(self); + let mut token = Token::root(); + //TODO: track usage by GPU + hub.compute_pipelines.unregister(compute_pipeline_id, &mut token); + } } fn validate_swap_chain_descriptor( diff --git a/gfx/wgpu/wgpu-core/src/hub.rs b/gfx/wgpu/wgpu-core/src/hub.rs index 208ed5ad97c2..7c0cfc369b30 100644 --- a/gfx/wgpu/wgpu-core/src/hub.rs +++ b/gfx/wgpu/wgpu-core/src/hub.rs @@ -39,7 +39,7 @@ use vec_map::VecMap; #[cfg(debug_assertions)] use std::cell::Cell; -use std::{marker::PhantomData, ops}; +use std::{fmt::Debug, marker::PhantomData, ops}; /// A simple structure to manage identities of objects. @@ -251,13 +251,13 @@ impl<'a, T> Drop for Token<'a, T> { } -pub trait IdentityFilter { - type Input: Clone; +pub trait IdentityFilter: Debug { + type Input: Clone + Debug; fn process(&self, id: Self::Input, backend: Backend) -> I; fn free(&self, id: I); } -impl IdentityFilter for () { +impl IdentityFilter for () { type Input = I; fn process(&self, id: I, _backend: Backend) -> I { //debug_assert_eq!(id.unzip().2, backend); @@ -266,7 +266,7 @@ impl IdentityFilter for () { fn free(&self, _id: I) {} } -impl IdentityFilter for Mutex { +impl IdentityFilter for Mutex { type Input = PhantomData; fn process(&self, _id: Self::Input, backend: Backend) -> I { self.lock().alloc(backend) diff --git a/gfx/wgpu/wgpu-core/src/lib.rs b/gfx/wgpu/wgpu-core/src/lib.rs index d6e2fc9208b7..4239b2992ae1 100644 --- a/gfx/wgpu/wgpu-core/src/lib.rs +++ b/gfx/wgpu/wgpu-core/src/lib.rs @@ -55,6 +55,7 @@ pub enum Backend { } pub type BufferAddress = u64; +pub type DynamicOffset = u32; pub type RawString = *const c_char; //TODO: make it private. Currently used for swapchain creation impl. diff --git a/gfx/wgpu/wgpu-core/src/resource.rs b/gfx/wgpu/wgpu-core/src/resource.rs index 1456fbb44966..7baa64df9176 100644 --- a/gfx/wgpu/wgpu-core/src/resource.rs +++ b/gfx/wgpu/wgpu-core/src/resource.rs @@ -32,8 +32,8 @@ bitflags::bitflags! { const VERTEX = 32; const UNIFORM = 64; const STORAGE = 128; - const STORAGE_READ = 256; - const INDIRECT = 512; + const INDIRECT = 256; + const STORAGE_READ = 512; const NONE = 0; /// The combination of all read-only usages. const READ_ALL = Self::MAP_READ.bits | Self::COPY_SRC.bits | diff --git a/gfx/wgpu/wgpu-remote/src/lib.rs b/gfx/wgpu/wgpu-remote/src/lib.rs index a979d8991b3b..798db2a7e178 100644 --- a/gfx/wgpu/wgpu-remote/src/lib.rs +++ b/gfx/wgpu/wgpu-remote/src/lib.rs @@ -27,6 +27,11 @@ struct IdentityHub { devices: IdentityManager, buffers: IdentityManager, command_buffers: IdentityManager, + bind_group_layouts: IdentityManager, + pipeline_layouts: IdentityManager, + bind_groups: IdentityManager, + shader_modules: IdentityManager, + compute_pipelines: IdentityManager, } #[derive(Debug, Default)] @@ -200,3 +205,138 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass( pub unsafe extern "C" fn wgpu_compute_pass_destroy(pass: core::command::RawPass) { let _ = pass.into_vec(); } + +#[no_mangle] +pub extern "C" fn wgpu_client_make_bind_group_layout_id( + client: &Client, + device_id: id::DeviceId, +) -> id::BindGroupLayoutId { + let backend = device_id.backend(); + client + .identities + .lock() + .select(backend) + .bind_group_layouts + .alloc(backend) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_kill_bind_group_layout_id( + client: &Client, + id: id::BindGroupLayoutId, +) { + client + .identities + .lock() + .select(id.backend()) + .bind_group_layouts + .free(id) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_make_pipeline_layout_id( + client: &Client, + device_id: id::DeviceId, +) -> id::PipelineLayoutId { + let backend = device_id.backend(); + client + .identities + .lock() + .select(backend) + .pipeline_layouts + .alloc(backend) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_kill_pipeline_layout_id( + client: &Client, + id: id::PipelineLayoutId, +) { + client + .identities + .lock() + .select(id.backend()) + .pipeline_layouts + .free(id) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_make_bind_group_id( + client: &Client, + device_id: id::DeviceId, +) -> id::BindGroupId { + let backend = device_id.backend(); + client + .identities + .lock() + .select(backend) + .bind_groups + .alloc(backend) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_kill_bind_group_id( + client: &Client, + id: id::BindGroupId, +) { + client + .identities + .lock() + .select(id.backend()) + .bind_groups + .free(id) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_make_shader_module_id( + client: &Client, + device_id: id::DeviceId, +) -> id::ShaderModuleId { + let backend = device_id.backend(); + client + .identities + .lock() + .select(backend) + .shader_modules + .alloc(backend) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_kill_shader_module_id( + client: &Client, + id: id::ShaderModuleId, +) { + client + .identities + .lock() + .select(id.backend()) + .shader_modules + .free(id) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_make_compute_pipeline_id( + client: &Client, + device_id: id::DeviceId, +) -> id::ComputePipelineId { + let backend = device_id.backend(); + client + .identities + .lock() + .select(backend) + .compute_pipelines + .alloc(backend) +} + +#[no_mangle] +pub extern "C" fn wgpu_client_kill_compute_pipeline_id( + client: &Client, + id: id::ComputePipelineId, +) { + client + .identities + .lock() + .select(id.backend()) + .compute_pipelines + .free(id) +} diff --git a/gfx/wgpu/wgpu-remote/src/server.rs b/gfx/wgpu/wgpu-remote/src/server.rs index 1a1c14f3c571..deaf559cdf52 100644 --- a/gfx/wgpu/wgpu-remote/src/server.rs +++ b/gfx/wgpu/wgpu-remote/src/server.rs @@ -127,9 +127,9 @@ pub extern "C" fn wgpu_server_device_create_encoder( global: &Global, self_id: id::DeviceId, desc: &core::command::CommandEncoderDescriptor, - encoder_id: id::CommandEncoderId, + new_id: id::CommandEncoderId, ) { - gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, encoder_id)); + gfx_select!(self_id => global.device_create_command_encoder(self_id, &desc, new_id)); } #[no_mangle] @@ -157,6 +157,19 @@ pub extern "C" fn wgpu_server_command_buffer_destroy( gfx_select!(self_id => global.command_buffer_destroy(self_id)); } +#[no_mangle] +pub unsafe extern "C" fn wgpu_server_encoder_copy_buffer_to_buffer( + global: &Global, + self_id: id::CommandEncoderId, + source_id: id::BufferId, + source_offset: core::BufferAddress, + destination_id: id::BufferId, + destination_offset: core::BufferAddress, + size: core::BufferAddress, +) { + gfx_select!(self_id => global.command_encoder_copy_buffer_to_buffer(self_id, source_id, source_offset, destination_id, destination_offset, size)); +} + #[no_mangle] pub unsafe extern "C" fn wgpu_server_encode_compute_pass( global: &Global, @@ -193,3 +206,93 @@ pub unsafe extern "C" fn wgpu_server_queue_submit( let command_buffers = slice::from_raw_parts(command_buffer_ids, command_buffer_id_length); gfx_select!(self_id => global.queue_submit(self_id, command_buffers)); } + +#[no_mangle] +pub extern "C" fn wgpu_server_device_create_bind_group_layout( + global: &Global, + self_id: id::DeviceId, + desc: &core::binding_model::BindGroupLayoutDescriptor, + new_id: id::BindGroupLayoutId, +) { + gfx_select!(self_id => global.device_create_bind_group_layout(self_id, desc, new_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_bind_group_layout_destroy( + global: &Global, + self_id: id::BindGroupLayoutId, +) { + gfx_select!(self_id => global.bind_group_layout_destroy(self_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_device_create_pipeline_layout( + global: &Global, + self_id: id::DeviceId, + desc: &core::binding_model::PipelineLayoutDescriptor, + new_id: id::PipelineLayoutId, +) { + gfx_select!(self_id => global.device_create_pipeline_layout(self_id, desc, new_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_pipeline_layout_destroy( + global: &Global, + self_id: id::PipelineLayoutId, +) { + gfx_select!(self_id => global.pipeline_layout_destroy(self_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_device_create_bind_group( + global: &Global, + self_id: id::DeviceId, + desc: &core::binding_model::BindGroupDescriptor, + new_id: id::BindGroupId, +) { + gfx_select!(self_id => global.device_create_bind_group(self_id, desc, new_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_bind_group_destroy( + global: &Global, + self_id: id::BindGroupId, +) { + gfx_select!(self_id => global.bind_group_destroy(self_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_device_create_shader_module( + global: &Global, + self_id: id::DeviceId, + desc: &core::pipeline::ShaderModuleDescriptor, + new_id: id::ShaderModuleId, +) { + gfx_select!(self_id => global.device_create_shader_module(self_id, desc, new_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_shader_module_destroy( + global: &Global, + self_id: id::ShaderModuleId, +) { + gfx_select!(self_id => global.shader_module_destroy(self_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_device_create_compute_pipeline( + global: &Global, + self_id: id::DeviceId, + desc: &core::pipeline::ComputePipelineDescriptor, + new_id: id::ComputePipelineId, +) { + gfx_select!(self_id => global.device_create_compute_pipeline(self_id, desc, new_id)); +} + +#[no_mangle] +pub extern "C" fn wgpu_server_compute_pipeline_destroy( + global: &Global, + self_id: id::ComputePipelineId, +) { + gfx_select!(self_id => global.compute_pipeline_destroy(self_id)); +}