mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1609175 - WebGPU bind groups and compute pipelines r=jgilbert,webidl,smaug,bzbarsky
Adds support for bind groups and compute pipelines The end goal of this PR is to run the compute example. Differential Revision: https://phabricator.services.mozilla.com/D60746 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
9e3c203f89
commit
73eff15f2c
@ -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<dom::Promise> Adapter::RequestDevice(
|
||||
const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv) {
|
||||
RefPtr<dom::Promise> promise = dom::Promise::Create(GetParentObject(), aRv);
|
||||
|
@ -29,19 +29,19 @@ class Adapter final : public ObjectBase, public ChildOf<Instance> {
|
||||
GPU_DECL_CYCLE_COLLECTION(Adapter)
|
||||
GPU_DECL_JS_WRAP(Adapter)
|
||||
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
|
||||
private:
|
||||
Adapter() = delete;
|
||||
~Adapter();
|
||||
void Cleanup();
|
||||
|
||||
const RefPtr<WebGPUChild> 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<dom::Promise> RequestDevice(
|
||||
const dom::GPUDeviceDescriptor& aDesc, ErrorResult& aRv);
|
||||
|
@ -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
|
||||
|
@ -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<Device> {
|
||||
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();
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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<Device> {
|
||||
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();
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -34,11 +34,12 @@ class Buffer final : public ObjectBase, public ChildOf<Device> {
|
||||
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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,20 +38,26 @@ class CommandEncoder final : public ObjectBase, public ChildOf<Device> {
|
||||
GPU_DECL_JS_WRAP(CommandEncoder)
|
||||
|
||||
CommandEncoder(Device* const aParent, WebGPUChild* const aBridge, RawId aId);
|
||||
RawId GetId() const { return mId; }
|
||||
void EndComputePass(Span<const uint8_t> aData, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<ComputePassEncoder> BeginComputePass(
|
||||
const dom::GPUComputePassDescriptor& aDesc);
|
||||
already_AddRefed<CommandBuffer> Finish(
|
||||
const dom::GPUCommandBufferDescriptor& aDesc);
|
||||
const RawId mId;
|
||||
|
||||
private:
|
||||
~CommandEncoder();
|
||||
void Cleanup();
|
||||
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
const RawId mId;
|
||||
|
||||
public:
|
||||
void EndComputePass(Span<const uint8_t> aData, ErrorResult& aRv);
|
||||
|
||||
void CopyBufferToBuffer(const Buffer& aSource, BufferAddress aSourceOffset,
|
||||
const Buffer& aDestination,
|
||||
BufferAddress aDestinationOffset,
|
||||
BufferAddress aSize);
|
||||
already_AddRefed<ComputePassEncoder> BeginComputePass(
|
||||
const dom::GPUComputePassDescriptor& aDesc);
|
||||
already_AddRefed<CommandBuffer> Finish(
|
||||
const dom::GPUCommandBufferDescriptor& aDesc);
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -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<uint32_t>& 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);
|
||||
|
@ -37,6 +37,9 @@ class ComputePassEncoder final : public ProgrammablePassEncoder,
|
||||
ffi::WGPURawPass mRaw;
|
||||
|
||||
public:
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets) override;
|
||||
void SetPipeline(const ComputePipeline& aPipeline);
|
||||
void Dispatch(uint32_t x, uint32_t y, uint32_t z);
|
||||
void EndPass(ErrorResult& aRv);
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -19,10 +19,13 @@ class ComputePipeline final : public ObjectBase, public ChildOf<Device> {
|
||||
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
|
||||
|
@ -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<ipc::Shmem> aShmem) {
|
||||
mBridge->SendDeviceUnmapBuffer(mId, aId, std::move(*aShmem));
|
||||
}
|
||||
|
||||
void Device::DestroyBuffer(RawId aId) {
|
||||
if (mBridge && mBridge->IsOpen()) {
|
||||
mBridge->DestroyBuffer(aId);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<CommandEncoder> Device::CreateCommandEncoder(
|
||||
const dom::GPUCommandEncoderDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateCommandEncoder(mId, aDesc);
|
||||
@ -142,16 +136,37 @@ already_AddRefed<CommandEncoder> Device::CreateCommandEncoder(
|
||||
return encoder.forget();
|
||||
}
|
||||
|
||||
void Device::DestroyCommandEncoder(RawId aId) {
|
||||
if (mBridge && mBridge->IsOpen()) {
|
||||
mBridge->DestroyCommandEncoder(aId);
|
||||
}
|
||||
already_AddRefed<BindGroupLayout> Device::CreateBindGroupLayout(
|
||||
const dom::GPUBindGroupLayoutDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateBindGroupLayout(mId, aDesc);
|
||||
RefPtr<BindGroupLayout> object = new BindGroupLayout(this, id);
|
||||
return object.forget();
|
||||
}
|
||||
already_AddRefed<PipelineLayout> Device::CreatePipelineLayout(
|
||||
const dom::GPUPipelineLayoutDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreatePipelineLayout(mId, aDesc);
|
||||
RefPtr<PipelineLayout> object = new PipelineLayout(this, id);
|
||||
return object.forget();
|
||||
}
|
||||
already_AddRefed<BindGroup> Device::CreateBindGroup(
|
||||
const dom::GPUBindGroupDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateBindGroup(mId, aDesc);
|
||||
RefPtr<BindGroup> object = new BindGroup(this, id);
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
void Device::DestroyCommandBuffer(RawId aId) {
|
||||
if (mBridge && mBridge->IsOpen()) {
|
||||
mBridge->DestroyCommandBuffer(aId);
|
||||
}
|
||||
already_AddRefed<ShaderModule> Device::CreateShaderModule(
|
||||
const dom::GPUShaderModuleDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateShaderModule(mId, aDesc);
|
||||
RefPtr<ShaderModule> object = new ShaderModule(this, id);
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ComputePipeline> Device::CreateComputePipeline(
|
||||
const dom::GPUComputePipelineDescriptor& aDesc) {
|
||||
RawId id = mBridge->DeviceCreateComputePipeline(mId, aDesc);
|
||||
RefPtr<ComputePipeline> object = new ComputePipeline(this, id);
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -79,15 +79,13 @@ class Device final : public DOMEventTargetHelper {
|
||||
RefPtr<MappingPromise> MapBufferForReadAsync(RawId aId, size_t aSize,
|
||||
ErrorResult& aRv);
|
||||
void UnmapBuffer(RawId aId, UniquePtr<ipc::Shmem> aShmem);
|
||||
void DestroyBuffer(RawId aId);
|
||||
void DestroyCommandEncoder(RawId aId);
|
||||
void DestroyCommandBuffer(RawId aId);
|
||||
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
|
||||
private:
|
||||
~Device();
|
||||
void Cleanup();
|
||||
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
const RawId mId;
|
||||
bool mValid = true;
|
||||
nsString mLabel;
|
||||
@ -105,6 +103,19 @@ class Device final : public DOMEventTargetHelper {
|
||||
|
||||
already_AddRefed<CommandEncoder> CreateCommandEncoder(
|
||||
const dom::GPUCommandEncoderDescriptor& aDesc);
|
||||
|
||||
already_AddRefed<BindGroupLayout> CreateBindGroupLayout(
|
||||
const dom::GPUBindGroupLayoutDescriptor& aDesc);
|
||||
already_AddRefed<PipelineLayout> CreatePipelineLayout(
|
||||
const dom::GPUPipelineLayoutDescriptor& aDesc);
|
||||
already_AddRefed<BindGroup> CreateBindGroup(
|
||||
const dom::GPUBindGroupDescriptor& aDesc);
|
||||
|
||||
already_AddRefed<ShaderModule> CreateShaderModule(
|
||||
const dom::GPUShaderModuleDescriptor& aDesc);
|
||||
already_AddRefed<ComputePipeline> CreateComputePipeline(
|
||||
const dom::GPUComputePipelineDescriptor& aDesc);
|
||||
|
||||
// IMPL_EVENT_HANDLER(uncapturederror)
|
||||
};
|
||||
|
||||
|
@ -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> Instance::Create(nsIGlobalObject* aOwner) {
|
||||
@ -34,7 +34,7 @@ already_AddRefed<Instance> 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<dom::Promise> Instance::RequestAdapter(
|
||||
const dom::GPURequestAdapterOptions& aOptions, ErrorResult& aRv) {
|
||||
RefPtr<dom::Promise> promise = dom::Promise::Create(mOwner, aRv);
|
||||
|
@ -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<Instance> Create(nsIGlobalObject* aOwner);
|
||||
|
||||
already_AddRefed<dom::Promise> RequestAdapter(
|
||||
const dom::GPURequestAdapterOptions& aOptions, ErrorResult& aRv);
|
||||
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
|
||||
private:
|
||||
explicit Instance(nsIGlobalObject* aOwner, WebGPUChild* aBridge);
|
||||
virtual ~Instance();
|
||||
void Cleanup();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
const RefPtr<WebGPUChild> mBridge;
|
||||
|
||||
public:
|
||||
nsIGlobalObject* GetParentObject() const { return mOwner; }
|
||||
WebGPUChild* GetBridge() const;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -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
|
||||
|
@ -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<Device> {
|
||||
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
|
||||
|
@ -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 {
|
||||
|
@ -13,8 +13,6 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
template <typename T>
|
||||
class Sequence;
|
||||
template <typename T>
|
||||
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<uint32_t>& aDynamicOffsets) = 0;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -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<uint32_t>& aDynamicOffsets) {
|
||||
if (mValid) {
|
||||
MOZ_CRASH("TODO");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mozilla
|
||||
|
@ -29,6 +29,8 @@ class RenderBundleEncoder final : public RenderEncoderBase,
|
||||
~RenderBundleEncoder() = default;
|
||||
|
||||
public:
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets) override;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -21,5 +21,13 @@ GPU_IMPL_JS_WRAP(RenderPassEncoder)
|
||||
|
||||
RenderPassEncoder::~RenderPassEncoder() = default;
|
||||
|
||||
void RenderPassEncoder::SetBindGroup(
|
||||
uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets) {
|
||||
if (mValid) {
|
||||
MOZ_CRASH("TODO");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mozilla
|
||||
|
@ -39,6 +39,8 @@ class RenderPassEncoder final : public RenderEncoderBase,
|
||||
void Cleanup() {}
|
||||
|
||||
public:
|
||||
void SetBindGroup(uint32_t aSlot, const BindGroup& aBindGroup,
|
||||
const dom::Sequence<uint32_t>& aDynamicOffsets) override;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
@ -19,6 +19,8 @@ class Sampler final : public ObjectBase, public ChildOf<Device> {
|
||||
GPU_DECL_CYCLE_COLLECTION(Sampler)
|
||||
GPU_DECL_JS_WRAP(Sampler)
|
||||
|
||||
const RawId mId;
|
||||
|
||||
private:
|
||||
Sampler() = delete;
|
||||
virtual ~Sampler();
|
||||
|
@ -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
|
||||
|
@ -19,10 +19,13 @@ class ShaderModule final : public ObjectBase, public ChildOf<Device> {
|
||||
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
|
||||
|
@ -19,6 +19,8 @@ class TextureView final : public ObjectBase, public ChildOf<Device> {
|
||||
GPU_DECL_CYCLE_COLLECTION(TextureView)
|
||||
GPU_DECL_JS_WRAP(TextureView)
|
||||
|
||||
const RawId mId;
|
||||
|
||||
private:
|
||||
TextureView() = delete;
|
||||
virtual ~TextureView();
|
||||
|
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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<ffi::WGPUBindGroupLayoutBinding> 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<uint32_t> 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<RawId>& 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
|
||||
|
@ -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<RawId>& 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();
|
||||
|
@ -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<uint8_t>(),
|
||||
@ -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<ffi::WGPUBindGroupBinding> 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<uint32_t>& 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);
|
||||
|
@ -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<RawId>& 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<uint32_t>& 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:
|
||||
|
@ -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<something> \
|
||||
: public ContiguousEnumSerializer<something, something(0), \
|
||||
something::EndGuard_> {}
|
||||
#define DEFINE_IPC_SERIALIZER_ENUM_GUARD(something, guard) \
|
||||
template <> \
|
||||
struct ParamTraits<something> \
|
||||
: public ContiguousEnumSerializer<something, something(0), guard> {}
|
||||
|
||||
#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_
|
||||
|
@ -7,15 +7,56 @@
|
||||
#define WEBGPU_TYPES_H_
|
||||
|
||||
#include <cstdint>
|
||||
#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<ffi::WGPUBindGroupLayoutBinding> mBindings;
|
||||
};
|
||||
|
||||
struct SerialPipelineLayoutDescriptor {
|
||||
nsTArray<RawId> 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<SerialBindGroupBinding> mBindings;
|
||||
};
|
||||
|
||||
struct SerialProgrammableStageDescriptor {
|
||||
RawId mModule;
|
||||
nsString mEntryPoint;
|
||||
};
|
||||
|
||||
struct SerialComputePipelineDescriptor {
|
||||
RawId mLayout;
|
||||
SerialProgrammableStageDescriptor mComputeStage;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // WEBGPU_TYPES_H_
|
||||
|
@ -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<u64> dynamicOffsets);
|
||||
void setBindGroup(unsigned long index, GPUBindGroup bindGroup,
|
||||
optional sequence<unsigned long> 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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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::Item> {
|
||||
self.iter
|
||||
.next()
|
||||
@ -58,7 +58,7 @@ impl<'a> Iterator for FollowUpIter<'a> {
|
||||
pub struct BindGroupEntry {
|
||||
expected_layout_id: Option<BindGroupLayoutId>,
|
||||
provided: Option<BindGroupPair>,
|
||||
dynamic_offsets: Vec<BufferAddress>,
|
||||
dynamic_offsets: Vec<DynamicOffset>,
|
||||
}
|
||||
|
||||
impl BindGroupEntry {
|
||||
@ -66,7 +66,7 @@ impl BindGroupEntry {
|
||||
&mut self,
|
||||
bind_group_id: BindGroupId,
|
||||
bind_group: &BindGroup<B>,
|
||||
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<B>,
|
||||
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());
|
||||
|
@ -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<BufferAddress>,
|
||||
phantom_offsets: PhantomSlice<DynamicOffset>,
|
||||
},
|
||||
SetPipeline(id::ComputePipelineId),
|
||||
Dispatch([u32; 3]),
|
||||
@ -95,7 +96,7 @@ impl<F> Global<F> {
|
||||
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 {
|
||||
|
@ -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<BufferAddress>,
|
||||
phantom_offsets: PhantomSlice<DynamicOffset>,
|
||||
},
|
||||
SetPipeline(id::RenderPipelineId),
|
||||
SetIndexBuffer {
|
||||
@ -798,7 +799,7 @@ impl<F> Global<F> {
|
||||
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 {
|
||||
|
@ -498,6 +498,8 @@ impl<F: IdentityFilter<id::BufferId>> Global<F> {
|
||||
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<F: IdentityFilter<id::BindGroupLayoutId>> Global<F> {
|
||||
.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<F: IdentityFilter<id::BindGroupLayoutId>> Global<F> {
|
||||
hub.bind_group_layouts
|
||||
.register_identity(id_in, layout, &mut token)
|
||||
}
|
||||
|
||||
pub fn bind_group_layout_destroy<B: GfxBackend>(&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<F: IdentityFilter<id::PipelineLayoutId>> Global<F> {
|
||||
@ -967,6 +978,13 @@ impl<F: IdentityFilter<id::PipelineLayoutId>> Global<F> {
|
||||
hub.pipeline_layouts
|
||||
.register_identity(id_in, layout, &mut token)
|
||||
}
|
||||
|
||||
pub fn pipeline_layout_destroy<B: GfxBackend>(&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<F: IdentityFilter<id::BindGroupId>> Global<F> {
|
||||
@ -1200,6 +1218,13 @@ impl<F: IdentityFilter<id::ShaderModuleId>> Global<F> {
|
||||
hub.shader_modules
|
||||
.register_identity(id_in, shader, &mut token)
|
||||
}
|
||||
|
||||
pub fn shader_module_destroy<B: GfxBackend>(&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<F: IdentityFilter<id::CommandEncoderId>> Global<F> {
|
||||
@ -1718,6 +1743,13 @@ impl<F: IdentityFilter<id::RenderPipelineId>> Global<F> {
|
||||
hub.render_pipelines
|
||||
.register_identity(id_in, pipeline, &mut token)
|
||||
}
|
||||
|
||||
pub fn render_pipeline_destroy<B: GfxBackend>(&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<F: IdentityFilter<id::ComputePipelineId>> Global<F> {
|
||||
@ -1773,6 +1805,13 @@ impl<F: IdentityFilter<id::ComputePipelineId>> Global<F> {
|
||||
hub.compute_pipelines
|
||||
.register_identity(id_in, pipeline, &mut token)
|
||||
}
|
||||
|
||||
pub fn compute_pipeline_destroy<B: GfxBackend>(&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(
|
||||
|
@ -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<I> {
|
||||
type Input: Clone;
|
||||
pub trait IdentityFilter<I>: Debug {
|
||||
type Input: Clone + Debug;
|
||||
fn process(&self, id: Self::Input, backend: Backend) -> I;
|
||||
fn free(&self, id: I);
|
||||
}
|
||||
|
||||
impl<I: TypedId + Clone> IdentityFilter<I> for () {
|
||||
impl<I: TypedId + Clone + Debug> IdentityFilter<I> for () {
|
||||
type Input = I;
|
||||
fn process(&self, id: I, _backend: Backend) -> I {
|
||||
//debug_assert_eq!(id.unzip().2, backend);
|
||||
@ -266,7 +266,7 @@ impl<I: TypedId + Clone> IdentityFilter<I> for () {
|
||||
fn free(&self, _id: I) {}
|
||||
}
|
||||
|
||||
impl<I: TypedId> IdentityFilter<I> for Mutex<IdentityManager> {
|
||||
impl<I: TypedId + Debug> IdentityFilter<I> for Mutex<IdentityManager> {
|
||||
type Input = PhantomData<I>;
|
||||
fn process(&self, _id: Self::Input, backend: Backend) -> I {
|
||||
self.lock().alloc(backend)
|
||||
|
@ -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.
|
||||
|
@ -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 |
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user