From 5668f013a9ef5c22cf962ae304234500e974061b Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 19 Oct 2020 17:19:12 +0000 Subject: [PATCH] Bug 1622846 - WebGPU new mapping API r=webidl,jgilbert,smaug This PR updates wgpu to https://github.com/gfx-rs/wgpu/commit/64ae59072db443eb1e47ee14d77370eec9f4b012 It has a number of things (API updates, correctness fixes, etc), but the biggest part is the new mapping API. Differential Revision: https://phabricator.services.mozilla.com/D92636 --- Cargo.lock | 8 +- dom/bindings/Bindings.conf | 3 + dom/webgpu/Buffer.cpp | 111 +- dom/webgpu/Buffer.h | 33 +- dom/webgpu/Device.cpp | 132 +- dom/webgpu/Device.h | 17 +- dom/webgpu/ffi/wgpu_ffi_generated.h | 1591 +++++++++++++++++ dom/webgpu/ipc/PWebGPU.ipdl | 14 +- dom/webgpu/ipc/WebGPUChild.cpp | 57 +- dom/webgpu/ipc/WebGPUChild.h | 1 - dom/webgpu/ipc/WebGPUParent.cpp | 195 +- dom/webgpu/ipc/WebGPUParent.h | 25 +- dom/webgpu/ipc/WebGPUSerialize.h | 16 +- dom/webgpu/ipc/WebGPUTypes.h | 46 +- dom/webgpu/mochitest/test_buffer_mapping.html | 22 +- dom/webidl/WebGPU.webidl | 20 +- gfx/wgpu/Cargo.lock | 377 ++-- gfx/wgpu/README.md | 2 +- gfx/wgpu/player/src/main.rs | 36 +- gfx/wgpu/wgpu-core/Cargo.toml | 12 +- gfx/wgpu/wgpu-core/src/binding_model.rs | 75 +- gfx/wgpu/wgpu-core/src/command/mod.rs | 2 + gfx/wgpu/wgpu-core/src/command/render.rs | 217 ++- gfx/wgpu/wgpu-core/src/command/transfer.rs | 254 +++ gfx/wgpu/wgpu-core/src/conv.rs | 57 +- gfx/wgpu/wgpu-core/src/device/life.rs | 27 +- gfx/wgpu/wgpu-core/src/device/mod.rs | 878 +++++---- gfx/wgpu/wgpu-core/src/device/queue.rs | 59 +- gfx/wgpu/wgpu-core/src/device/trace.rs | 3 +- gfx/wgpu/wgpu-core/src/hub.rs | 3 +- gfx/wgpu/wgpu-core/src/instance.rs | 120 +- gfx/wgpu/wgpu-core/src/lib.rs | 4 +- gfx/wgpu/wgpu-core/src/pipeline.rs | 23 + gfx/wgpu/wgpu-core/src/resource.rs | 74 +- gfx/wgpu/wgpu-core/src/track/texture.rs | 6 +- gfx/wgpu/wgpu-core/src/validation.rs | 614 +++++++ gfx/wgpu/wgpu-types/src/lib.rs | 302 +++- gfx/wgpu_bindings/cbindgen.toml | 6 +- gfx/wgpu_bindings/moz.build | 2 +- gfx/wgpu_bindings/src/server.rs | 253 ++- .../gfx-backend-dx12/.cargo-checksum.json | 2 +- third_party/rust/gfx-backend-dx12/Cargo.toml | 6 +- .../rust/gfx-backend-dx12/src/command.rs | 96 +- third_party/rust/gfx-backend-dx12/src/conv.rs | 67 +- .../rust/gfx-backend-dx12/src/device.rs | 131 +- third_party/rust/gfx-backend-dx12/src/lib.rs | 30 +- .../rust/gfx-backend-dx12/src/resource.rs | 4 +- .../rust/gfx-backend-dx12/src/window.rs | 28 +- .../rust/range-alloc/.cargo-checksum.json | 2 +- third_party/rust/range-alloc/Cargo.toml | 5 +- third_party/rust/range-alloc/src/lib.rs | 173 +- 51 files changed, 4941 insertions(+), 1300 deletions(-) create mode 100644 dom/webgpu/ffi/wgpu_ffi_generated.h create mode 100644 gfx/wgpu/wgpu-core/src/validation.rs diff --git a/Cargo.lock b/Cargo.lock index 259a1121e610..3a7f604c9171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1826,9 +1826,9 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.5.3" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37365e2927d55cefac0d3f78dfd1d3119fbb13a8bd7afe2409d729961fee22fc" +checksum = "cfd506627f3a7003e80f4344123184ce60ed06822c8b8ad2ae4ec674a512ca86" dependencies = [ "bitflags", "d3d12", @@ -3999,9 +3999,9 @@ dependencies = [ [[package]] name = "range-alloc" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5927936723a9e8b715d37d7e4b390455087c4bdf25b9f702309460577b14f9" +checksum = "a871f1e45a3a3f0c73fb60343c811238bb5143a81642e27c2ac7aac27ff01a63" [[package]] name = "raw-cpuid" diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 642dcafc95a9..30be303a64a4 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1425,6 +1425,9 @@ DOMInterfaces = { 'GPULoadOp': { 'concrete': False, }, +'GPUMapMode': { + 'concrete': False, +}, 'GPUPrimitiveTopology': { 'concrete': False, }, diff --git a/dom/webgpu/Buffer.cpp b/dom/webgpu/Buffer.cpp index 77fb2ff4c87c..96bd392c6e56 100644 --- a/dom/webgpu/Buffer.cpp +++ b/dom/webgpu/Buffer.cpp @@ -8,6 +8,7 @@ #include "mozilla/dom/ScriptSettings.h" #include "mozilla/ipc/Shmem.h" +#include "js/RootingAPI.h" #include "nsContentUtils.h" #include "nsWrapperCache.h" #include "Device.h" @@ -30,17 +31,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Buffer) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Buffer) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER - if (tmp->mMapping) { - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMapping->mArrayBuffer) + if (tmp->mMapped) { + for (uint32_t i = 0; i < tmp->mMapped->mArrayBuffers.Length(); ++i) { + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK( + mMapped->mArrayBuffers[i]) + } } NS_IMPL_CYCLE_COLLECTION_TRACE_END -Buffer::Mapping::Mapping(ipc::Shmem&& aShmem, JSObject* aArrayBuffer, - bool aWrite) - : mShmem(MakeUnique(std::move(aShmem))), - mArrayBuffer(aArrayBuffer), - mWrite(aWrite) {} - Buffer::Buffer(Device* const aParent, RawId aId, BufferAddress aSize) : ChildOf(aParent), mId(aId), mSize(aSize) { mozilla::HoldJSObjects(this); @@ -52,30 +50,42 @@ Buffer::~Buffer() { } void Buffer::Cleanup() { - if (mParent) { + if (mValid && mParent) { + mValid = false; auto bridge = mParent->GetBridge(); if (bridge && bridge->IsOpen()) { bridge->SendBufferDestroy(mId); } + if (bridge && mMapped) { + bridge->DeallocShmem(mMapped->mShmem); + } } - mMapping.reset(); } -void Buffer::InitMapping(ipc::Shmem&& aShmem, JSObject* aArrayBuffer, - bool aWrite) { - mMapping.emplace(std::move(aShmem), aArrayBuffer, aWrite); +void Buffer::SetMapped(ipc::Shmem&& aShmem, bool aWritable) { + MOZ_ASSERT(!mMapped); + mMapped.emplace(); + mMapped->mShmem = std::move(aShmem); + mMapped->mWritable = aWritable; } -already_AddRefed Buffer::MapReadAsync(ErrorResult& aRv) { +already_AddRefed Buffer::MapAsync( + uint32_t aMode, uint64_t aOffset, const dom::Optional& aSize, + ErrorResult& aRv) { RefPtr promise = dom::Promise::Create(GetParentObject(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - if (mMapping) { + if (mMapped) { aRv.ThrowInvalidStateError("Unable to map a buffer that is already mapped"); return nullptr; } - const auto checked = CheckedInt(mSize); + // Initialize with a dummy shmem, it will become real after the promise is + // resolved. + SetMapped(ipc::Shmem(), aMode == dom::GPUMapMode_Binding::WRITE); + + const auto checked = aSize.WasPassed() ? CheckedInt(aSize.Value()) + : CheckedInt(mSize) - aOffset; if (!checked.isValid()) { aRv.ThrowRangeError("Mapped size is too large"); return nullptr; @@ -84,32 +94,16 @@ already_AddRefed Buffer::MapReadAsync(ErrorResult& aRv) { const auto& size = checked.value(); RefPtr self(this); - auto mappingPromise = mParent->MapBufferForReadAsync(mId, size, aRv); + auto mappingPromise = mParent->MapBufferAsync(mId, aMode, aOffset, size, aRv); if (!mappingPromise) { return nullptr; } mappingPromise->Then( GetMainThreadSerialEventTarget(), __func__, - [promise, size, self](ipc::Shmem&& aShmem) { - MOZ_ASSERT(aShmem.Size() == size); - dom::AutoJSAPI jsapi; - if (!jsapi.Init(self->GetParentObject())) { - promise->MaybeRejectWithAbortError("Owning page was unloaded!"); - return; - } - JS::Rooted arrayBuffer( - jsapi.cx(), - Device::CreateExternalArrayBuffer(jsapi.cx(), size, aShmem)); - if (!arrayBuffer) { - ErrorResult rv; - rv.StealExceptionFromJSContext(jsapi.cx()); - promise->MaybeReject(std::move(rv)); - return; - } - JS::Rooted val(jsapi.cx(), JS::ObjectValue(*arrayBuffer)); - self->mMapping.emplace(std::move(aShmem), arrayBuffer, false); - promise->MaybeResolve(val); + [promise, self](ipc::Shmem&& aShmem) { + self->mMapped->mShmem = std::move(aShmem); + promise->MaybeResolve(0); }, [promise](const ipc::ResponseRejectReason&) { promise->MaybeRejectWithAbortError("Internal communication error!"); @@ -118,18 +112,49 @@ already_AddRefed Buffer::MapReadAsync(ErrorResult& aRv) { return promise.forget(); } -void Buffer::Unmap(JSContext* aCx, ErrorResult& aRv) { - if (!mMapping) { +void Buffer::GetMappedRange(JSContext* aCx, uint64_t aOffset, + const dom::Optional& aSize, + JS::Rooted* aObject, ErrorResult& aRv) { + const auto checkedOffset = CheckedInt(aOffset); + const auto checkedSize = aSize.WasPassed() + ? CheckedInt(aSize.Value()) + : CheckedInt(mSize) - aOffset; + if (!checkedOffset.isValid() || !checkedSize.isValid()) { + aRv.ThrowRangeError("Invalid mapped range"); return; } - JS::Rooted rooted(aCx, mMapping->mArrayBuffer); - bool ok = JS::DetachArrayBuffer(aCx, rooted); - if (!ok) { + if (!mMapped || !mMapped->IsReady()) { + aRv.ThrowInvalidStateError("Buffer is not mapped"); + return; + } + + auto* const arrayBuffer = mParent->CreateExternalArrayBuffer( + aCx, checkedOffset.value(), checkedSize.value(), mMapped->mShmem); + if (!arrayBuffer) { aRv.NoteJSContextException(aCx); return; } - mParent->UnmapBuffer(mId, std::move(mMapping->mShmem), mMapping->mWrite); - mMapping.reset(); + + aObject->set(arrayBuffer); + mMapped->mArrayBuffers.AppendElement(*aObject); +} + +void Buffer::Unmap(JSContext* aCx, ErrorResult& aRv) { + if (!mMapped) { + return; + } + + for (const auto& arrayBuffer : mMapped->mArrayBuffers) { + JS::Rooted rooted(aCx, arrayBuffer); + bool ok = JS::DetachArrayBuffer(aCx, rooted); + if (!ok) { + aRv.NoteJSContextException(aCx); + return; + } + }; + + mParent->UnmapBuffer(mId, std::move(mMapped->mShmem), mMapped->mWritable); + mMapped.reset(); } void Buffer::Destroy() { diff --git a/dom/webgpu/Buffer.h b/dom/webgpu/Buffer.h index 2f09ed163dfd..4b7537cc6d51 100644 --- a/dom/webgpu/Buffer.h +++ b/dom/webgpu/Buffer.h @@ -8,6 +8,7 @@ #include "js/RootingAPI.h" #include "mozilla/dom/Nullable.h" +#include "mozilla/ipc/Shmem.h" #include "mozilla/webgpu/WebGPUTypes.h" #include "ObjectModel.h" @@ -19,21 +20,25 @@ namespace webgpu { class Device; +struct MappedInfo { + ipc::Shmem mShmem; + // True if mapping is requested for writing. + bool mWritable = false; + // Populated by `GetMappedRange`. + nsTArray> mArrayBuffers; + + MappedInfo() = default; + MappedInfo(const MappedInfo&) = delete; + bool IsReady() const { return mShmem.IsReadable(); } +}; + class Buffer final : public ObjectBase, public ChildOf { public: GPU_DECL_CYCLE_COLLECTION(Buffer) GPU_DECL_JS_WRAP(Buffer) - struct Mapping final { - UniquePtr mShmem; - JS::Heap mArrayBuffer; - const bool mWrite; - - Mapping(ipc::Shmem&& aShmem, JSObject* aArrayBuffer, bool aWrite); - }; - Buffer(Device* const aParent, RawId aId, BufferAddress aSize); - void InitMapping(ipc::Shmem&& aShmem, JSObject* aArrayBuffer, bool aWrite); + void SetMapped(ipc::Shmem&& aShmem, bool aWritable); const RawId mId; @@ -46,10 +51,16 @@ class Buffer final : public ObjectBase, public ChildOf { // are mapped. const BufferAddress mSize; nsString mLabel; - Maybe mMapping; + // Information about the currently active mapping. + Maybe mMapped; public: - already_AddRefed MapReadAsync(ErrorResult& aRv); + already_AddRefed MapAsync(uint32_t aMode, uint64_t aOffset, + const dom::Optional& aSize, + ErrorResult& aRv); + void GetMappedRange(JSContext* aCx, uint64_t aOffset, + const dom::Optional& aSize, + JS::Rooted* aObject, ErrorResult& aRv); void Unmap(JSContext* aCx, ErrorResult& aRv); void Destroy(); }; diff --git a/dom/webgpu/Device.cpp b/dom/webgpu/Device.cpp index ca643b2c0cf0..e71b06e4d005 100644 --- a/dom/webgpu/Device.cpp +++ b/dom/webgpu/Device.cpp @@ -37,10 +37,11 @@ static void mapFreeCallback(void* aContents, void* aUserData) { RefPtr Device::GetBridge() { return mBridge; } -JSObject* Device::CreateExternalArrayBuffer(JSContext* aCx, size_t aSize, - ipc::Shmem& aShmem) { - MOZ_ASSERT(aShmem.Size() == aSize); - return JS::NewExternalArrayBuffer(aCx, aSize, aShmem.get(), +JSObject* Device::CreateExternalArrayBuffer(JSContext* aCx, size_t aOffset, + size_t aSize, + const ipc::Shmem& aShmem) { + MOZ_ASSERT(aOffset + aSize <= aShmem.Size()); + return JS::NewExternalArrayBuffer(aCx, aSize, aShmem.get() + aOffset, &mapFreeCallback, nullptr); } @@ -65,74 +66,79 @@ void Device::SetLabel(const nsAString& aLabel) { mLabel = aLabel; } Queue* Device::DefaultQueue() const { return mQueue; } already_AddRefed Device::CreateBuffer( - const dom::GPUBufferDescriptor& aDesc) { + const dom::GPUBufferDescriptor& aDesc, ErrorResult& aRv) { + ipc::Shmem shmem; + bool hasMapFlags = aDesc.mUsage & (dom::GPUBufferUsage_Binding::MAP_WRITE | + dom::GPUBufferUsage_Binding::MAP_READ); + if (hasMapFlags || aDesc.mMappedAtCreation) { + const auto checked = CheckedInt(aDesc.mSize); + if (!checked.isValid()) { + aRv.ThrowRangeError("Mappable size is too large"); + return nullptr; + } + const auto& size = checked.value(); + + // TODO: use `ShmemPool`? + if (!mBridge->AllocShmem(size, ipc::Shmem::SharedMemory::TYPE_BASIC, + &shmem)) { + aRv.ThrowAbortError( + nsPrintfCString("Unable to allocate shmem of size %" PRIuPTR, size)); + return nullptr; + } + + // zero out memory + memset(shmem.get(), 0, size); + } + + // If the buffer is not mapped at creation, and it has Shmem, we send it + // to the GPU process. Otherwise, we keep it. RawId id = mBridge->DeviceCreateBuffer(mId, aDesc); + if (hasMapFlags && !aDesc.mMappedAtCreation) { + mBridge->SendBufferReturnShmem(id, std::move(shmem)); + } RefPtr buffer = new Buffer(this, id, aDesc.mSize); + + if (aDesc.mMappedAtCreation) { + buffer->SetMapped(std::move(shmem), + !(aDesc.mUsage & dom::GPUBufferUsage_Binding::MAP_READ)); + } + return buffer.forget(); } -void Device::CreateBufferMapped(JSContext* aCx, - const dom::GPUBufferDescriptor& aDesc, - nsTArray& aSequence, - ErrorResult& aRv) { - const auto checked = CheckedInt(aDesc.mSize); - if (!checked.isValid()) { +RefPtr Device::MapBufferAsync(RawId aId, uint32_t aMode, + size_t aOffset, size_t aSize, + ErrorResult& aRv) { + ffi::WGPUHostMap mode; + switch (aMode) { + case dom::GPUMapMode_Binding::READ: + mode = ffi::WGPUHostMap_Read; + break; + case dom::GPUMapMode_Binding::WRITE: + mode = ffi::WGPUHostMap_Write; + break; + default: + aRv.ThrowInvalidAccessError( + nsPrintfCString("Invalid map flag %u", aMode)); + return nullptr; + } + + const CheckedInt offset(aOffset); + if (!offset.isValid()) { + aRv.ThrowRangeError("Mapped offset is too large"); + return nullptr; + } + const CheckedInt size(aSize); + if (!size.isValid()) { aRv.ThrowRangeError("Mapped size is too large"); - return; - } - const auto& size = checked.value(); - - // TODO: use `ShmemPool` - ipc::Shmem shmem; - if (!mBridge->AllocShmem(size, ipc::Shmem::SharedMemory::TYPE_BASIC, - &shmem)) { - aRv.ThrowAbortError( - nsPrintfCString("Unable to allocate shmem of size %" PRIuPTR, size)); - return; - } - - // zero out memory - memset(shmem.get(), 0, size); - - JS::Rooted arrayBuffer( - aCx, CreateExternalArrayBuffer(aCx, size, shmem)); - if (!arrayBuffer) { - aRv.NoteJSContextException(aCx); - return; - } - - dom::GPUBufferDescriptor modifiedDesc(aDesc); - modifiedDesc.mUsage |= dom::GPUBufferUsage_Binding::MAP_WRITE; - RawId id = mBridge->DeviceCreateBuffer(mId, modifiedDesc); - RefPtr buffer = new Buffer(this, id, aDesc.mSize); - - JS::Rooted bufferValue(aCx); - if (!dom::ToJSValue(aCx, buffer, &bufferValue)) { - aRv.NoteJSContextException(aCx); - return; - } - - aSequence.AppendElement(bufferValue); - aSequence.AppendElement(JS::ObjectValue(*arrayBuffer)); - - buffer->InitMapping(std::move(shmem), arrayBuffer, true); -} - -RefPtr Device::MapBufferForReadAsync(RawId aId, size_t aSize, - ErrorResult& aRv) { - ipc::Shmem shmem; - if (!mBridge->AllocShmem(aSize, ipc::Shmem::SharedMemory::TYPE_BASIC, - &shmem)) { - aRv.ThrowAbortError( - nsPrintfCString("Unable to allocate shmem of size %" PRIuPTR, aSize)); return nullptr; } - return mBridge->SendBufferMapRead(aId, std::move(shmem)); + return mBridge->SendBufferMap(aId, mode, offset.value(), size.value()); } -void Device::UnmapBuffer(RawId aId, UniquePtr aShmem, bool aFlush) { - mBridge->SendDeviceUnmapBuffer(mId, aId, std::move(*aShmem), aFlush); +void Device::UnmapBuffer(RawId aId, ipc::Shmem&& aShmem, bool aFlush) { + mBridge->SendBufferUnmap(aId, std::move(aShmem), aFlush); } already_AddRefed Device::CreateTexture( @@ -177,6 +183,10 @@ already_AddRefed Device::CreateBindGroup( already_AddRefed Device::CreateShaderModule( const dom::GPUShaderModuleDescriptor& aDesc) { + if (aDesc.mCode.IsString()) { + // we don't yet support WGSL + return nullptr; + } RawId id = mBridge->DeviceCreateShaderModule(mId, aDesc); RefPtr object = new ShaderModule(this, id); return object.forget(); diff --git a/dom/webgpu/Device.h b/dom/webgpu/Device.h index 2ee86ddc6e26..33e14bc68dc6 100644 --- a/dom/webgpu/Device.h +++ b/dom/webgpu/Device.h @@ -78,11 +78,13 @@ class Device final : public DOMEventTargetHelper { explicit Device(Adapter* const aParent, RawId aId); RefPtr GetBridge(); - static JSObject* CreateExternalArrayBuffer(JSContext* aCx, size_t aSize, - ipc::Shmem& aShmem); - RefPtr MapBufferForReadAsync(RawId aId, size_t aSize, - ErrorResult& aRv); - void UnmapBuffer(RawId aId, UniquePtr aShmem, bool aFlush); + static JSObject* CreateExternalArrayBuffer(JSContext* aCx, size_t aOffset, + size_t aSize, + const ipc::Shmem& aShmem); + RefPtr MapBufferAsync(RawId aId, uint32_t aMode, + size_t aOffset, size_t aSize, + ErrorResult& aRv); + void UnmapBuffer(RawId aId, ipc::Shmem&& aShmem, bool aFlush); already_AddRefed InitSwapChain( const dom::GPUSwapChainDescriptor& aDesc, const dom::GPUExtent3DDict& aExtent3D, @@ -104,9 +106,8 @@ class Device final : public DOMEventTargetHelper { Queue* DefaultQueue() const; - already_AddRefed CreateBuffer(const dom::GPUBufferDescriptor& aDesc); - void CreateBufferMapped(JSContext* aCx, const dom::GPUBufferDescriptor& aDesc, - nsTArray& aSequence, ErrorResult& aRv); + already_AddRefed CreateBuffer(const dom::GPUBufferDescriptor& aDesc, + ErrorResult& aRv); already_AddRefed CreateTexture( const dom::GPUTextureDescriptor& aDesc); diff --git a/dom/webgpu/ffi/wgpu_ffi_generated.h b/dom/webgpu/ffi/wgpu_ffi_generated.h new file mode 100644 index 000000000000..2f8d11e727e5 --- /dev/null +++ b/dom/webgpu/ffi/wgpu_ffi_generated.h @@ -0,0 +1,1591 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Generated with cbindgen:0.14.4 */ + +/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. + * To generate this file: + * 1. Get the latest cbindgen using `cargo install --force cbindgen` + * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release + * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate wgpu_bindings -o dom/webgpu/ffi/wgpu_ffi_generated.h` + */ + +typedef uint64_t WGPUNonZeroU64; +typedef uint64_t WGPUOption_AdapterId; +typedef uint64_t WGPUOption_SurfaceId; +typedef uint64_t WGPUOption_TextureViewId; +typedef char WGPUNonExhaustive[0]; + + +#include +#include +#include +#include + +/** + * Bound uniform/storage buffer offsets must be aligned to this number. + */ +#define WGPUBIND_BUFFER_ALIGNMENT 256 + +/** + * Buffer to buffer copy offsets and sizes must be aligned to this number + */ +#define WGPUCOPY_BUFFER_ALIGNMENT 4 + +/** + * Buffer-Texture copies on command encoders have to have the `bytes_per_row` + * aligned to this number. + * + * This doesn't apply to `Queue::write_texture`. + */ +#define WGPUCOPY_BYTES_PER_ROW_ALIGNMENT 256 + +#define WGPUDEFAULT_BIND_GROUPS 4 + +#define WGPUDESIRED_NUM_FRAMES 3 + +#define WGPUMAX_ANISOTROPY 16 + +#define WGPUMAX_COLOR_TARGETS 4 + +#define WGPUMAX_MIP_LEVELS 16 + +#define WGPUMAX_VERTEX_BUFFERS 16 + +enum WGPUAddressMode { + WGPUAddressMode_ClampToEdge = 0, + WGPUAddressMode_Repeat = 1, + WGPUAddressMode_MirrorRepeat = 2, + /** + * Must be last for serialization purposes + */ + WGPUAddressMode_Sentinel, +}; + +enum WGPUBlendFactor { + WGPUBlendFactor_Zero = 0, + WGPUBlendFactor_One = 1, + WGPUBlendFactor_SrcColor = 2, + WGPUBlendFactor_OneMinusSrcColor = 3, + WGPUBlendFactor_SrcAlpha = 4, + WGPUBlendFactor_OneMinusSrcAlpha = 5, + WGPUBlendFactor_DstColor = 6, + WGPUBlendFactor_OneMinusDstColor = 7, + WGPUBlendFactor_DstAlpha = 8, + WGPUBlendFactor_OneMinusDstAlpha = 9, + WGPUBlendFactor_SrcAlphaSaturated = 10, + WGPUBlendFactor_BlendColor = 11, + WGPUBlendFactor_OneMinusBlendColor = 12, + /** + * Must be last for serialization purposes + */ + WGPUBlendFactor_Sentinel, +}; + +enum WGPUBlendOperation { + WGPUBlendOperation_Add = 0, + WGPUBlendOperation_Subtract = 1, + WGPUBlendOperation_ReverseSubtract = 2, + WGPUBlendOperation_Min = 3, + WGPUBlendOperation_Max = 4, + /** + * Must be last for serialization purposes + */ + WGPUBlendOperation_Sentinel, +}; + +enum WGPUBufferMapAsyncStatus { + WGPUBufferMapAsyncStatus_Success, + WGPUBufferMapAsyncStatus_Error, + WGPUBufferMapAsyncStatus_Unknown, + WGPUBufferMapAsyncStatus_ContextLost, + /** + * Must be last for serialization purposes + */ + WGPUBufferMapAsyncStatus_Sentinel, +}; + +enum WGPUCompareFunction { + WGPUCompareFunction_Undefined = 0, + WGPUCompareFunction_Never = 1, + WGPUCompareFunction_Less = 2, + WGPUCompareFunction_Equal = 3, + WGPUCompareFunction_LessEqual = 4, + WGPUCompareFunction_Greater = 5, + WGPUCompareFunction_NotEqual = 6, + WGPUCompareFunction_GreaterEqual = 7, + WGPUCompareFunction_Always = 8, + /** + * Must be last for serialization purposes + */ + WGPUCompareFunction_Sentinel, +}; + +enum WGPUCullMode { + WGPUCullMode_None = 0, + WGPUCullMode_Front = 1, + WGPUCullMode_Back = 2, + /** + * Must be last for serialization purposes + */ + WGPUCullMode_Sentinel, +}; + +enum WGPUFilterMode { + WGPUFilterMode_Nearest = 0, + WGPUFilterMode_Linear = 1, + /** + * Must be last for serialization purposes + */ + WGPUFilterMode_Sentinel, +}; + +enum WGPUFrontFace { + WGPUFrontFace_Ccw = 0, + WGPUFrontFace_Cw = 1, + /** + * Must be last for serialization purposes + */ + WGPUFrontFace_Sentinel, +}; + +enum WGPUHostMap { + WGPUHostMap_Read, + WGPUHostMap_Write, + /** + * Must be last for serialization purposes + */ + WGPUHostMap_Sentinel, +}; + +enum WGPUIndexFormat { + WGPUIndexFormat_Uint16 = 0, + WGPUIndexFormat_Uint32 = 1, + /** + * Must be last for serialization purposes + */ + WGPUIndexFormat_Sentinel, +}; + +enum WGPUInputStepMode { + WGPUInputStepMode_Vertex = 0, + WGPUInputStepMode_Instance = 1, + /** + * Must be last for serialization purposes + */ + WGPUInputStepMode_Sentinel, +}; + +enum WGPULoadOp { + WGPULoadOp_Clear = 0, + WGPULoadOp_Load = 1, + /** + * Must be last for serialization purposes + */ + WGPULoadOp_Sentinel, +}; + +enum WGPUPowerPreference { + WGPUPowerPreference_Default = 0, + WGPUPowerPreference_LowPower = 1, + WGPUPowerPreference_HighPerformance = 2, + /** + * Must be last for serialization purposes + */ + WGPUPowerPreference_Sentinel, +}; + +enum WGPUPrimitiveTopology { + WGPUPrimitiveTopology_PointList = 0, + WGPUPrimitiveTopology_LineList = 1, + WGPUPrimitiveTopology_LineStrip = 2, + WGPUPrimitiveTopology_TriangleList = 3, + WGPUPrimitiveTopology_TriangleStrip = 4, + /** + * Must be last for serialization purposes + */ + WGPUPrimitiveTopology_Sentinel, +}; + +enum WGPURawBindingType { + WGPURawBindingType_UniformBuffer, + WGPURawBindingType_StorageBuffer, + WGPURawBindingType_ReadonlyStorageBuffer, + WGPURawBindingType_Sampler, + WGPURawBindingType_ComparisonSampler, + WGPURawBindingType_SampledTexture, + WGPURawBindingType_ReadonlyStorageTexture, + WGPURawBindingType_WriteonlyStorageTexture, + /** + * Must be last for serialization purposes + */ + WGPURawBindingType_Sentinel, +}; + +enum WGPUStencilOperation { + WGPUStencilOperation_Keep = 0, + WGPUStencilOperation_Zero = 1, + WGPUStencilOperation_Replace = 2, + WGPUStencilOperation_Invert = 3, + WGPUStencilOperation_IncrementClamp = 4, + WGPUStencilOperation_DecrementClamp = 5, + WGPUStencilOperation_IncrementWrap = 6, + WGPUStencilOperation_DecrementWrap = 7, + /** + * Must be last for serialization purposes + */ + WGPUStencilOperation_Sentinel, +}; + +enum WGPUStoreOp { + WGPUStoreOp_Clear = 0, + WGPUStoreOp_Store = 1, + /** + * Must be last for serialization purposes + */ + WGPUStoreOp_Sentinel, +}; + +enum WGPUTextureAspect { + WGPUTextureAspect_All, + WGPUTextureAspect_StencilOnly, + WGPUTextureAspect_DepthOnly, + /** + * Must be last for serialization purposes + */ + WGPUTextureAspect_Sentinel, +}; + +enum WGPUTextureComponentType { + WGPUTextureComponentType_Float, + WGPUTextureComponentType_Sint, + WGPUTextureComponentType_Uint, + /** + * Must be last for serialization purposes + */ + WGPUTextureComponentType_Sentinel, +}; + +enum WGPUTextureDimension { + WGPUTextureDimension_D1, + WGPUTextureDimension_D2, + WGPUTextureDimension_D3, + /** + * Must be last for serialization purposes + */ + WGPUTextureDimension_Sentinel, +}; + +enum WGPUTextureFormat { + WGPUTextureFormat_R8Unorm = 0, + WGPUTextureFormat_R8Snorm = 1, + WGPUTextureFormat_R8Uint = 2, + WGPUTextureFormat_R8Sint = 3, + WGPUTextureFormat_R16Uint = 4, + WGPUTextureFormat_R16Sint = 5, + WGPUTextureFormat_R16Float = 6, + WGPUTextureFormat_Rg8Unorm = 7, + WGPUTextureFormat_Rg8Snorm = 8, + WGPUTextureFormat_Rg8Uint = 9, + WGPUTextureFormat_Rg8Sint = 10, + WGPUTextureFormat_R32Uint = 11, + WGPUTextureFormat_R32Sint = 12, + WGPUTextureFormat_R32Float = 13, + WGPUTextureFormat_Rg16Uint = 14, + WGPUTextureFormat_Rg16Sint = 15, + WGPUTextureFormat_Rg16Float = 16, + WGPUTextureFormat_Rgba8Unorm = 17, + WGPUTextureFormat_Rgba8UnormSrgb = 18, + WGPUTextureFormat_Rgba8Snorm = 19, + WGPUTextureFormat_Rgba8Uint = 20, + WGPUTextureFormat_Rgba8Sint = 21, + WGPUTextureFormat_Bgra8Unorm = 22, + WGPUTextureFormat_Bgra8UnormSrgb = 23, + WGPUTextureFormat_Rgb10a2Unorm = 24, + WGPUTextureFormat_Rg11b10Float = 25, + WGPUTextureFormat_Rg32Uint = 26, + WGPUTextureFormat_Rg32Sint = 27, + WGPUTextureFormat_Rg32Float = 28, + WGPUTextureFormat_Rgba16Uint = 29, + WGPUTextureFormat_Rgba16Sint = 30, + WGPUTextureFormat_Rgba16Float = 31, + WGPUTextureFormat_Rgba32Uint = 32, + WGPUTextureFormat_Rgba32Sint = 33, + WGPUTextureFormat_Rgba32Float = 34, + WGPUTextureFormat_Depth32Float = 35, + WGPUTextureFormat_Depth24Plus = 36, + WGPUTextureFormat_Depth24PlusStencil8 = 37, + /** + * Must be last for serialization purposes + */ + WGPUTextureFormat_Sentinel, +}; + +enum WGPUTextureViewDimension { + WGPUTextureViewDimension_D1, + WGPUTextureViewDimension_D2, + WGPUTextureViewDimension_D2Array, + WGPUTextureViewDimension_Cube, + WGPUTextureViewDimension_CubeArray, + WGPUTextureViewDimension_D3, + /** + * Must be last for serialization purposes + */ + WGPUTextureViewDimension_Sentinel, +}; + +enum WGPUVertexFormat { + WGPUVertexFormat_Uchar2 = 0, + WGPUVertexFormat_Uchar4 = 1, + WGPUVertexFormat_Char2 = 2, + WGPUVertexFormat_Char4 = 3, + WGPUVertexFormat_Uchar2Norm = 4, + WGPUVertexFormat_Uchar4Norm = 5, + WGPUVertexFormat_Char2Norm = 6, + WGPUVertexFormat_Char4Norm = 7, + WGPUVertexFormat_Ushort2 = 8, + WGPUVertexFormat_Ushort4 = 9, + WGPUVertexFormat_Short2 = 10, + WGPUVertexFormat_Short4 = 11, + WGPUVertexFormat_Ushort2Norm = 12, + WGPUVertexFormat_Ushort4Norm = 13, + WGPUVertexFormat_Short2Norm = 14, + WGPUVertexFormat_Short4Norm = 15, + WGPUVertexFormat_Half2 = 16, + WGPUVertexFormat_Half4 = 17, + WGPUVertexFormat_Float = 18, + WGPUVertexFormat_Float2 = 19, + WGPUVertexFormat_Float3 = 20, + WGPUVertexFormat_Float4 = 21, + WGPUVertexFormat_Uint = 22, + WGPUVertexFormat_Uint2 = 23, + WGPUVertexFormat_Uint3 = 24, + WGPUVertexFormat_Uint4 = 25, + WGPUVertexFormat_Int = 26, + WGPUVertexFormat_Int2 = 27, + WGPUVertexFormat_Int3 = 28, + WGPUVertexFormat_Int4 = 29, + /** + * Must be last for serialization purposes + */ + WGPUVertexFormat_Sentinel, +}; + +struct WGPUBindGroupDescriptor; + +/** + * The internal enum mirrored from `BufferUsage`. The values don't have to match! + */ +struct WGPUBufferUse; + +struct WGPUClient; + +struct WGPUGlobal; + +/** + * The internal enum mirrored from `TextureUsage`. The values don't have to match! + */ +struct WGPUTextureUse; + +typedef uint64_t WGPUBufferSize; + +typedef WGPUNonZeroU64 WGPUId_Adapter_Dummy; + +typedef WGPUId_Adapter_Dummy WGPUAdapterId; + +typedef WGPUNonZeroU64 WGPUId_BindGroup_Dummy; + +typedef WGPUId_BindGroup_Dummy WGPUBindGroupId; + +typedef WGPUNonZeroU64 WGPUId_BindGroupLayout_Dummy; + +typedef WGPUId_BindGroupLayout_Dummy WGPUBindGroupLayoutId; + +typedef WGPUNonZeroU64 WGPUId_Buffer_Dummy; + +typedef WGPUId_Buffer_Dummy WGPUBufferId; + +typedef WGPUNonZeroU64 WGPUId_ComputePipeline_Dummy; + +typedef WGPUId_ComputePipeline_Dummy WGPUComputePipelineId; + +typedef WGPUNonZeroU64 WGPUId_Device_Dummy; + +typedef WGPUId_Device_Dummy WGPUDeviceId; + +typedef WGPUNonZeroU64 WGPUId_CommandBuffer_Dummy; + +typedef WGPUId_CommandBuffer_Dummy WGPUCommandBufferId; + +typedef WGPUCommandBufferId WGPUCommandEncoderId; + +typedef WGPUNonZeroU64 WGPUId_PipelineLayout_Dummy; + +typedef WGPUId_PipelineLayout_Dummy WGPUPipelineLayoutId; + +typedef WGPUNonZeroU64 WGPUId_RenderPipeline_Dummy; + +typedef WGPUId_RenderPipeline_Dummy WGPURenderPipelineId; + +typedef WGPUNonZeroU64 WGPUId_Sampler_Dummy; + +typedef WGPUId_Sampler_Dummy WGPUSamplerId; + +typedef WGPUNonZeroU64 WGPUId_ShaderModule_Dummy; + +typedef WGPUId_ShaderModule_Dummy WGPUShaderModuleId; + +typedef WGPUNonZeroU64 WGPUId_Texture_Dummy; + +typedef WGPUId_Texture_Dummy WGPUTextureId; + +typedef WGPUNonZeroU64 WGPUId_TextureView_Dummy; + +typedef WGPUId_TextureView_Dummy WGPUTextureViewId; + +struct WGPUInfrastructure { + struct WGPUClient *client; + const uint8_t *error; +}; + +struct WGPURawPass { + uint8_t *data; + uint8_t *base; + uintptr_t capacity; + WGPUCommandEncoderId parent; +}; + +struct WGPUComputePassDescriptor { + uint32_t todo; +}; + +struct WGPUColor { + double r; + double g; + double b; + double a; +}; +#define WGPUColor_TRANSPARENT (WGPUColor){ .r = 0.0, .g = 0.0, .b = 0.0, .a = 0.0 } +#define WGPUColor_BLACK (WGPUColor){ .r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0 } +#define WGPUColor_WHITE (WGPUColor){ .r = 1.0, .g = 1.0, .b = 1.0, .a = 1.0 } +#define WGPUColor_RED (WGPUColor){ .r = 1.0, .g = 0.0, .b = 0.0, .a = 1.0 } +#define WGPUColor_GREEN (WGPUColor){ .r = 0.0, .g = 1.0, .b = 0.0, .a = 1.0 } +#define WGPUColor_BLUE (WGPUColor){ .r = 0.0, .g = 0.0, .b = 1.0, .a = 1.0 } + +struct WGPURenderPassColorAttachmentDescriptorBase_TextureViewId { + WGPUTextureViewId attachment; + WGPUOption_TextureViewId resolve_target; + enum WGPULoadOp load_op; + enum WGPUStoreOp store_op; + struct WGPUColor clear_color; +}; + +typedef struct WGPURenderPassColorAttachmentDescriptorBase_TextureViewId WGPURenderPassColorAttachmentDescriptor; + +struct WGPURenderPassDepthStencilAttachmentDescriptorBase_TextureViewId { + WGPUTextureViewId attachment; + enum WGPULoadOp depth_load_op; + enum WGPUStoreOp depth_store_op; + float clear_depth; + bool depth_read_only; + enum WGPULoadOp stencil_load_op; + enum WGPUStoreOp stencil_store_op; + uint32_t clear_stencil; + bool stencil_read_only; +}; + +typedef struct WGPURenderPassDepthStencilAttachmentDescriptorBase_TextureViewId WGPURenderPassDepthStencilAttachmentDescriptor; + +struct WGPURenderPassDescriptor { + const WGPURenderPassColorAttachmentDescriptor *color_attachments; + uintptr_t color_attachments_length; + const WGPURenderPassDepthStencilAttachmentDescriptor *depth_stencil_attachment; +}; + +typedef uint64_t WGPUBufferAddress; + +typedef const char *WGPURawString; + +typedef uint32_t WGPUDynamicOffset; + +typedef WGPUNonZeroU64 WGPUId_RenderBundle_Dummy; + +typedef WGPUId_RenderBundle_Dummy WGPURenderBundleId; + +typedef uint64_t WGPUExtensions; +/** + * Allow anisotropic filtering in samplers. + * + * Supported platforms: + * - OpenGL 4.6+ (or 1.2+ with widespread GL_EXT_texture_filter_anisotropic) + * - DX11/12 + * - Metal + * - Vulkan + * + * This is a native only extension. Support is planned to be added to webgpu, + * but it is not yet implemented. + * + * https://github.com/gpuweb/gpuweb/issues/696 + */ +#define WGPUExtensions_ANISOTROPIC_FILTERING (uint64_t)65536 +/** + * Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with + * COPY_DST and COPY_SRC respectively. This removes this requirement. + * + * This is only beneficial on systems that share memory between CPU and GPU. If enabled + * on a system that doesn't, this can severely hinder performance. Only use if you understand + * the consequences. + * + * Supported platforms: + * - All + * + * This is a native only extension. + */ +#define WGPUExtensions_MAPPABLE_PRIMARY_BUFFERS (uint64_t)131072 +/** + * Allows the user to create uniform arrays of textures in shaders: + * + * eg. `uniform texture2D textures[10]`. + * + * This extension only allows them to exist and to be indexed by compile time constant + * values. + * + * Supported platforms: + * - DX12 + * - Metal (with MSL 2.0+ on macOS 10.13+) + * - Vulkan + * + * This is a native only extension. + */ +#define WGPUExtensions_TEXTURE_BINDING_ARRAY (uint64_t)262144 +/** + * Extensions which are part of the upstream webgpu standard + */ +#define WGPUExtensions_ALL_WEBGPU (uint64_t)65535 +/** + * Extensions that require activating the unsafe extension flag + */ +#define WGPUExtensions_ALL_UNSAFE (uint64_t)18446462598732840960ULL +/** + * Extensions that are only available when targeting native (not web) + */ +#define WGPUExtensions_ALL_NATIVE (uint64_t)18446744073709486080ULL + +struct WGPULimits { + uint32_t max_bind_groups; + WGPUNonExhaustive _non_exhaustive; +}; + +struct WGPUDeviceDescriptor { + WGPUExtensions extensions; + struct WGPULimits limits; + /** + * Switch shader validation on/off. This is a temporary field + * that will be removed once our validation logic is complete. + */ + bool shader_validation; +}; + +typedef void (*WGPUBufferMapCallback)(enum WGPUBufferMapAsyncStatus status, uint8_t *userdata); + +struct WGPUBufferMapOperation { + enum WGPUHostMap host; + WGPUBufferMapCallback callback; + uint8_t *user_data; +}; + +typedef uint32_t WGPUShaderStage; +#define WGPUShaderStage_NONE (uint32_t)0 +#define WGPUShaderStage_VERTEX (uint32_t)1 +#define WGPUShaderStage_FRAGMENT (uint32_t)2 +#define WGPUShaderStage_COMPUTE (uint32_t)4 + +typedef uint32_t WGPURawEnumOption_TextureViewDimension; + +typedef uint32_t WGPURawEnumOption_TextureComponentType; + +typedef uint32_t WGPURawEnumOption_TextureFormat; + +struct WGPUBindGroupLayoutEntry { + uint32_t binding; + WGPUShaderStage visibility; + enum WGPURawBindingType ty; + bool has_dynamic_offset; + WGPURawEnumOption_TextureViewDimension view_dimension; + WGPURawEnumOption_TextureComponentType texture_component_type; + bool multisampled; + WGPURawEnumOption_TextureFormat storage_texture_format; +}; + +struct WGPUBindGroupLayoutDescriptor { + WGPURawString label; + const struct WGPUBindGroupLayoutEntry *entries; + uintptr_t entries_length; +}; + +typedef uint32_t WGPUBufferUsage; +#define WGPUBufferUsage_MAP_READ (uint32_t)1 +#define WGPUBufferUsage_MAP_WRITE (uint32_t)2 +#define WGPUBufferUsage_COPY_SRC (uint32_t)4 +#define WGPUBufferUsage_COPY_DST (uint32_t)8 +#define WGPUBufferUsage_INDEX (uint32_t)16 +#define WGPUBufferUsage_VERTEX (uint32_t)32 +#define WGPUBufferUsage_UNIFORM (uint32_t)64 +#define WGPUBufferUsage_STORAGE (uint32_t)128 +#define WGPUBufferUsage_INDIRECT (uint32_t)256 + +struct WGPUBufferDescriptor { + WGPURawString label; + WGPUBufferAddress size; + WGPUBufferUsage usage; + bool mapped_at_creation; +}; + +struct WGPUProgrammableStageDescriptor { + WGPUShaderModuleId module; + WGPURawString entry_point; +}; + +struct WGPUComputePipelineDescriptor { + WGPUPipelineLayoutId layout; + struct WGPUProgrammableStageDescriptor compute_stage; +}; + +struct WGPUCommandEncoderDescriptor { + const char *label; +}; + +struct WGPUPipelineLayoutDescriptor { + const WGPUBindGroupLayoutId *bind_group_layouts; + uintptr_t bind_group_layouts_length; +}; + +struct WGPURasterizationStateDescriptor { + enum WGPUFrontFace front_face; + enum WGPUCullMode cull_mode; + int32_t depth_bias; + float depth_bias_slope_scale; + float depth_bias_clamp; +}; + +struct WGPUBlendDescriptor { + enum WGPUBlendFactor src_factor; + enum WGPUBlendFactor dst_factor; + enum WGPUBlendOperation operation; +}; + +typedef uint32_t WGPUColorWrite; +#define WGPUColorWrite_RED (uint32_t)1 +#define WGPUColorWrite_GREEN (uint32_t)2 +#define WGPUColorWrite_BLUE (uint32_t)4 +#define WGPUColorWrite_ALPHA (uint32_t)8 +#define WGPUColorWrite_COLOR (uint32_t)7 +#define WGPUColorWrite_ALL (uint32_t)15 + +struct WGPUColorStateDescriptor { + enum WGPUTextureFormat format; + struct WGPUBlendDescriptor alpha_blend; + struct WGPUBlendDescriptor color_blend; + WGPUColorWrite write_mask; +}; + +struct WGPUStencilStateFaceDescriptor { + enum WGPUCompareFunction compare; + enum WGPUStencilOperation fail_op; + enum WGPUStencilOperation depth_fail_op; + enum WGPUStencilOperation pass_op; +}; + +struct WGPUDepthStencilStateDescriptor { + enum WGPUTextureFormat format; + bool depth_write_enabled; + enum WGPUCompareFunction depth_compare; + struct WGPUStencilStateFaceDescriptor stencil_front; + struct WGPUStencilStateFaceDescriptor stencil_back; + uint32_t stencil_read_mask; + uint32_t stencil_write_mask; +}; + +typedef uint32_t WGPUShaderLocation; + +struct WGPUVertexAttributeDescriptor { + WGPUBufferAddress offset; + enum WGPUVertexFormat format; + WGPUShaderLocation shader_location; +}; + +struct WGPUVertexBufferLayoutDescriptor { + WGPUBufferAddress array_stride; + enum WGPUInputStepMode step_mode; + const struct WGPUVertexAttributeDescriptor *attributes; + uintptr_t attributes_length; +}; + +struct WGPUVertexStateDescriptor { + enum WGPUIndexFormat index_format; + const struct WGPUVertexBufferLayoutDescriptor *vertex_buffers; + uintptr_t vertex_buffers_length; +}; + +struct WGPURenderPipelineDescriptor { + WGPUPipelineLayoutId layout; + struct WGPUProgrammableStageDescriptor vertex_stage; + const struct WGPUProgrammableStageDescriptor *fragment_stage; + enum WGPUPrimitiveTopology primitive_topology; + const struct WGPURasterizationStateDescriptor *rasterization_state; + const struct WGPUColorStateDescriptor *color_states; + uintptr_t color_states_length; + const struct WGPUDepthStencilStateDescriptor *depth_stencil_state; + struct WGPUVertexStateDescriptor vertex_state; + uint32_t sample_count; + uint32_t sample_mask; + bool alpha_to_coverage_enabled; +}; + +struct WGPUSamplerDescriptor { + WGPURawString label; + enum WGPUAddressMode address_modes[3]; + enum WGPUFilterMode mag_filter; + enum WGPUFilterMode min_filter; + enum WGPUFilterMode mipmap_filter; + float lod_min_clamp; + float lod_max_clamp; + const enum WGPUCompareFunction *compare; + uint8_t anisotropy_clamp; +}; + +struct WGPUU32Array { + const uint32_t *bytes; + uintptr_t length; +}; + +struct WGPUShaderModuleDescriptor { + struct WGPUU32Array code; +}; + +struct WGPUExtent3d { + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +typedef uint32_t WGPUTextureUsage; +#define WGPUTextureUsage_COPY_SRC (uint32_t)1 +#define WGPUTextureUsage_COPY_DST (uint32_t)2 +#define WGPUTextureUsage_SAMPLED (uint32_t)4 +#define WGPUTextureUsage_STORAGE (uint32_t)8 +#define WGPUTextureUsage_OUTPUT_ATTACHMENT (uint32_t)16 + +struct WGPUTextureDescriptor { + WGPURawString label; + struct WGPUExtent3d size; + uint32_t mip_level_count; + uint32_t sample_count; + enum WGPUTextureDimension dimension; + enum WGPUTextureFormat format; + WGPUTextureUsage usage; +}; + +struct WGPUTextureDataLayout { + WGPUBufferAddress offset; + uint32_t bytes_per_row; + uint32_t rows_per_image; +}; + +struct WGPUBufferCopyView { + WGPUBufferId buffer; + struct WGPUTextureDataLayout layout; +}; + +struct WGPUOrigin3d { + uint32_t x; + uint32_t y; + uint32_t z; +}; +#define WGPUOrigin3d_ZERO (WGPUOrigin3d){ .x = 0, .y = 0, .z = 0 } + +struct WGPUTextureCopyView { + WGPUTextureId texture; + uint32_t mip_level; + struct WGPUOrigin3d origin; +}; + +struct WGPUCommandBufferDescriptor { + uint32_t todo; +}; + +struct WGPURequestAdapterOptions { + enum WGPUPowerPreference power_preference; + WGPUOption_SurfaceId compatible_surface; +}; + +typedef void *WGPUFactoryParam; + +typedef WGPUNonZeroU64 WGPUId_SwapChain_Dummy; + +typedef WGPUId_SwapChain_Dummy WGPUSwapChainId; + +typedef WGPUNonZeroU64 WGPUId_Surface; + +typedef WGPUId_Surface WGPUSurfaceId; + +struct WGPUIdentityRecyclerFactory { + WGPUFactoryParam param; + void (*free_adapter)(WGPUAdapterId, WGPUFactoryParam); + void (*free_device)(WGPUDeviceId, WGPUFactoryParam); + void (*free_swap_chain)(WGPUSwapChainId, WGPUFactoryParam); + void (*free_pipeline_layout)(WGPUPipelineLayoutId, WGPUFactoryParam); + void (*free_shader_module)(WGPUShaderModuleId, WGPUFactoryParam); + void (*free_bind_group_layout)(WGPUBindGroupLayoutId, WGPUFactoryParam); + void (*free_bind_group)(WGPUBindGroupId, WGPUFactoryParam); + void (*free_command_buffer)(WGPUCommandBufferId, WGPUFactoryParam); + void (*free_render_pipeline)(WGPURenderPipelineId, WGPUFactoryParam); + void (*free_compute_pipeline)(WGPUComputePipelineId, WGPUFactoryParam); + void (*free_buffer)(WGPUBufferId, WGPUFactoryParam); + void (*free_texture)(WGPUTextureId, WGPUFactoryParam); + void (*free_texture_view)(WGPUTextureViewId, WGPUFactoryParam); + void (*free_sampler)(WGPUSamplerId, WGPUFactoryParam); + void (*free_surface)(WGPUSurfaceId, WGPUFactoryParam); +}; + +typedef WGPUDeviceId WGPUQueueId; + +struct WGPUTextureViewDescriptor { + WGPURawString label; + enum WGPUTextureFormat format; + enum WGPUTextureViewDimension dimension; + enum WGPUTextureAspect aspect; + uint32_t base_mip_level; + uint32_t level_count; + uint32_t base_array_layer; + uint32_t array_layer_count; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +WGPU_INLINE +WGPUBufferSize make_buffer_size(uint64_t aRawSize) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe because improper use may lead to memory + * problems. For example, a double-free may occur if the function is called + * twice on the same raw pointer. + */ +WGPU_INLINE +void wgpu_client_delete(struct WGPUClient *aClient) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_adapter_id(const struct WGPUClient *aClient, + WGPUAdapterId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_bind_group_id(const struct WGPUClient *aClient, + WGPUBindGroupId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_bind_group_layout_id(const struct WGPUClient *aClient, + WGPUBindGroupLayoutId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_buffer_id(const struct WGPUClient *aClient, + WGPUBufferId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_compute_pipeline_id(const struct WGPUClient *aClient, + WGPUComputePipelineId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_device_id(const struct WGPUClient *aClient, + WGPUDeviceId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_encoder_id(const struct WGPUClient *aClient, + WGPUCommandEncoderId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_pipeline_layout_id(const struct WGPUClient *aClient, + WGPUPipelineLayoutId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_render_pipeline_id(const struct WGPUClient *aClient, + WGPURenderPipelineId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_sampler_id(const struct WGPUClient *aClient, + WGPUSamplerId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_shader_module_id(const struct WGPUClient *aClient, + WGPUShaderModuleId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_texture_id(const struct WGPUClient *aClient, + WGPUTextureId aId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_client_kill_texture_view_id(const struct WGPUClient *aClient, + WGPUTextureViewId aId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `id_length` elements. + */ +WGPU_INLINE +uintptr_t wgpu_client_make_adapter_ids(const struct WGPUClient *aClient, + WGPUAdapterId *aIds, + uintptr_t aIdLength) +WGPU_FUNC; + +WGPU_INLINE +WGPUBindGroupId wgpu_client_make_bind_group_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUBindGroupLayoutId wgpu_client_make_bind_group_layout_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUBufferId wgpu_client_make_buffer_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUComputePipelineId wgpu_client_make_compute_pipeline_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUDeviceId wgpu_client_make_device_id(const struct WGPUClient *aClient, + WGPUAdapterId aAdapterId) +WGPU_FUNC; + +WGPU_INLINE +WGPUCommandEncoderId wgpu_client_make_encoder_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUPipelineLayoutId wgpu_client_make_pipeline_layout_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPURenderPipelineId wgpu_client_make_render_pipeline_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUSamplerId wgpu_client_make_sampler_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUShaderModuleId wgpu_client_make_shader_module_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUTextureId wgpu_client_make_texture_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +WGPUTextureViewId wgpu_client_make_texture_view_id(const struct WGPUClient *aClient, + WGPUDeviceId aDeviceId) +WGPU_FUNC; + +WGPU_INLINE +struct WGPUInfrastructure wgpu_client_new(void) +WGPU_FUNC; + +WGPU_INLINE +struct WGPURawPass wgpu_command_encoder_begin_compute_pass(WGPUCommandEncoderId aEncoderId, + const struct WGPUComputePassDescriptor *aDesc) +WGPU_FUNC; + +WGPU_INLINE +struct WGPURawPass wgpu_command_encoder_begin_render_pass(WGPUCommandEncoderId aEncoderId, + const struct WGPURenderPassDescriptor *aDesc) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_destroy(struct WGPURawPass aPass) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_dispatch(struct WGPURawPass *aPass, + uint32_t aGroupsX, + uint32_t aGroupsY, + uint32_t aGroupsZ) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_dispatch_indirect(struct WGPURawPass *aPass, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset) +WGPU_FUNC; + +WGPU_INLINE +const uint8_t *wgpu_compute_pass_finish(struct WGPURawPass *aPass, + uintptr_t *aLength) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_insert_debug_marker(struct WGPURawPass *aPass, + WGPURawString aLabel) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_pop_debug_group(struct WGPURawPass *aPass) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_push_debug_group(struct WGPURawPass *aPass, + WGPURawString aLabel) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `offset_length` elements. + */ +WGPU_INLINE +void wgpu_compute_pass_set_bind_group(struct WGPURawPass *aPass, + uint32_t aIndex, + WGPUBindGroupId aBindGroupId, + const WGPUDynamicOffset *aOffsets, + uintptr_t aOffsetLength) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_compute_pass_set_pipeline(struct WGPURawPass *aPass, + WGPUComputePipelineId aPipelineId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_destroy(struct WGPURawPass aPass) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_draw(struct WGPURawPass *aPass, + uint32_t aVertexCount, + uint32_t aInstanceCount, + uint32_t aFirstVertex, + uint32_t aFirstInstance) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_draw_indexed(struct WGPURawPass *aPass, + uint32_t aIndexCount, + uint32_t aInstanceCount, + uint32_t aFirstIndex, + int32_t aBaseVertex, + uint32_t aFirstInstance) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_draw_indexed_indirect(struct WGPURawPass *aPass, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_draw_indirect(struct WGPURawPass *aPass, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_execute_bundles(struct WGPURawPass *aPass, + const WGPURenderBundleId *aBundles, + uintptr_t aBundlesLength) +WGPU_FUNC; + +WGPU_INLINE +const uint8_t *wgpu_render_pass_finish(struct WGPURawPass *aPass, + uintptr_t *aLength) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_insert_debug_marker(struct WGPURawPass *aPass, + WGPURawString aLabel) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_pop_debug_group(struct WGPURawPass *aPass) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_push_debug_group(struct WGPURawPass *aPass, + WGPURawString aLabel) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `offset_length` elements. + */ +WGPU_INLINE +void wgpu_render_pass_set_bind_group(struct WGPURawPass *aPass, + uint32_t aIndex, + WGPUBindGroupId aBindGroupId, + const WGPUDynamicOffset *aOffsets, + uintptr_t aOffsetLength) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_blend_color(struct WGPURawPass *aPass, + const struct WGPUColor *aColor) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_index_buffer(struct WGPURawPass *aPass, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset, + WGPUBufferSize aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_pipeline(struct WGPURawPass *aPass, + WGPURenderPipelineId aPipelineId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_scissor_rect(struct WGPURawPass *aPass, + uint32_t aX, + uint32_t aY, + uint32_t aW, + uint32_t aH) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_stencil_reference(struct WGPURawPass *aPass, + uint32_t aValue) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_vertex_buffer(struct WGPURawPass *aPass, + uint32_t aSlot, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset, + WGPUBufferSize aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_render_pass_set_viewport(struct WGPURawPass *aPass, + float aX, + float aY, + float aW, + float aH, + float aDepthMin, + float aDepthMax) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_adapter_destroy(const struct WGPUGlobal *aGlobal, + WGPUAdapterId aAdapterId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_adapter_request_device(const struct WGPUGlobal *aGlobal, + WGPUAdapterId aSelfId, + const struct WGPUDeviceDescriptor *aDesc, + WGPUDeviceId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_bind_group_destroy(const struct WGPUGlobal *aGlobal, + WGPUBindGroupId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_bind_group_layout_destroy(const struct WGPUGlobal *aGlobal, + WGPUBindGroupLayoutId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_buffer_destroy(const struct WGPUGlobal *aGlobal, + WGPUBufferId aSelfId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `size` elements. + */ +WGPU_INLINE +const uint8_t *wgpu_server_buffer_get_mapped_range(const struct WGPUGlobal *aGlobal, + WGPUBufferId aBufferId, + WGPUBufferAddress aStart, + WGPUBufferAddress aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_buffer_map(const struct WGPUGlobal *aGlobal, + WGPUBufferId aBufferId, + WGPUBufferAddress aStart, + WGPUBufferAddress aSize, + struct WGPUBufferMapOperation aOperation) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_buffer_unmap(const struct WGPUGlobal *aGlobal, + WGPUBufferId aBufferId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `byte_length` elements. + */ +WGPU_INLINE +void wgpu_server_command_buffer_destroy(const struct WGPUGlobal *aGlobal, + WGPUCommandBufferId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_compute_pipeline_destroy(const struct WGPUGlobal *aGlobal, + WGPUComputePipelineId aSelfId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe because improper use may lead to memory + * problems. For example, a double-free may occur if the function is called + * twice on the same raw pointer. + */ +WGPU_INLINE +void wgpu_server_delete(struct WGPUGlobal *aGlobal) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_bind_group(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUBindGroupDescriptor *aDesc, + WGPUBindGroupId aNewId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `entries_length` elements. + */ +WGPU_INLINE +void wgpu_server_device_create_bind_group_layout(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUBindGroupLayoutDescriptor *aDesc, + WGPUBindGroupLayoutId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_buffer(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUBufferDescriptor *aDesc, + WGPUBufferId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_compute_pipeline(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUComputePipelineDescriptor *aDesc, + WGPUComputePipelineId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_encoder(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUCommandEncoderDescriptor *aDesc, + WGPUCommandEncoderId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_pipeline_layout(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUPipelineLayoutDescriptor *aDesc, + WGPUPipelineLayoutId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_render_pipeline(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPURenderPipelineDescriptor *aDesc, + WGPURenderPipelineId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_sampler(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUSamplerDescriptor *aDesc, + WGPUSamplerId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_shader_module(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUShaderModuleDescriptor *aDesc, + WGPUShaderModuleId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_create_texture(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + const struct WGPUTextureDescriptor *aDesc, + WGPUTextureId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_device_destroy(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `size` elements. + */ +WGPU_INLINE +void wgpu_server_device_set_buffer_sub_data(const struct WGPUGlobal *aGlobal, + WGPUDeviceId aSelfId, + WGPUBufferId aBufferId, + WGPUBufferAddress aOffset, + const uint8_t *aData, + WGPUBufferAddress aSize) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointers are + * valid for `color_attachments_length` and `command_length` elements, + * respectively. + */ +WGPU_INLINE +void wgpu_server_encode_compute_pass(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const uint8_t *aBytes, + uintptr_t aByteLength) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointers are + * valid for `color_attachments_length` and `command_length` elements, + * respectively. + */ +WGPU_INLINE +void wgpu_server_encode_render_pass(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const uint8_t *aCommands, + uintptr_t aCommandLength) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_copy_buffer_to_buffer(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + WGPUBufferId aSourceId, + WGPUBufferAddress aSourceOffset, + WGPUBufferId aDestinationId, + WGPUBufferAddress aDestinationOffset, + WGPUBufferAddress aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_copy_buffer_to_texture(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const struct WGPUBufferCopyView *aSource, + const struct WGPUTextureCopyView *aDestination, + const struct WGPUExtent3d *aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_copy_texture_to_buffer(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const struct WGPUTextureCopyView *aSource, + const struct WGPUBufferCopyView *aDestination, + const struct WGPUExtent3d *aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_copy_texture_to_texture(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const struct WGPUTextureCopyView *aSource, + const struct WGPUTextureCopyView *aDestination, + const struct WGPUExtent3d *aSize) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_destroy(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_encoder_finish(const struct WGPUGlobal *aGlobal, + WGPUCommandEncoderId aSelfId, + const struct WGPUCommandBufferDescriptor *aDesc) +WGPU_FUNC; + +/** + * Request an adapter according to the specified options. + * Provide the list of IDs to pick from. + * + * Returns the index in this list, or -1 if unable to pick. + * + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `id_length` elements. + */ +WGPU_INLINE +int8_t wgpu_server_instance_request_adapter(const struct WGPUGlobal *aGlobal, + const struct WGPURequestAdapterOptions *aDesc, + const WGPUAdapterId *aIds, + uintptr_t aIdLength) +WGPU_FUNC; + +WGPU_INLINE +struct WGPUGlobal *wgpu_server_new(struct WGPUIdentityRecyclerFactory aFactory) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_pipeline_layout_destroy(const struct WGPUGlobal *aGlobal, + WGPUPipelineLayoutId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_poll_all_devices(const struct WGPUGlobal *aGlobal, + bool aForceWait) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `command_buffer_id_length` elements. + */ +WGPU_INLINE +void wgpu_server_queue_submit(const struct WGPUGlobal *aGlobal, + WGPUQueueId aSelfId, + const WGPUCommandBufferId *aCommandBufferIds, + uintptr_t aCommandBufferIdLength) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `data_length` elements. + */ +WGPU_INLINE +void wgpu_server_queue_write_buffer(const struct WGPUGlobal *aGlobal, + WGPUQueueId aSelfId, + WGPUBufferId aBufferId, + WGPUBufferAddress aBufferOffset, + const uint8_t *aData, + uintptr_t aDataLength) +WGPU_FUNC; + +/** + * # Safety + * + * This function is unsafe as there is no guarantee that the given pointer is + * valid for `data_length` elements. + */ +WGPU_INLINE +void wgpu_server_queue_write_texture(const struct WGPUGlobal *aGlobal, + WGPUQueueId aSelfId, + const struct WGPUTextureCopyView *aDestination, + const uint8_t *aData, + uintptr_t aDataLength, + const struct WGPUTextureDataLayout *aLayout, + const struct WGPUExtent3d *aExtent) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_render_pipeline_destroy(const struct WGPUGlobal *aGlobal, + WGPURenderPipelineId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_sampler_destroy(const struct WGPUGlobal *aGlobal, + WGPUSamplerId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_shader_module_destroy(const struct WGPUGlobal *aGlobal, + WGPUShaderModuleId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_texture_create_view(const struct WGPUGlobal *aGlobal, + WGPUTextureId aSelfId, + const struct WGPUTextureViewDescriptor *aDesc, + WGPUTextureViewId aNewId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_texture_destroy(const struct WGPUGlobal *aGlobal, + WGPUTextureId aSelfId) +WGPU_FUNC; + +WGPU_INLINE +void wgpu_server_texture_view_destroy(const struct WGPUGlobal *aGlobal, + WGPUTextureViewId aSelfId) +WGPU_FUNC; diff --git a/dom/webgpu/ipc/PWebGPU.ipdl b/dom/webgpu/ipc/PWebGPU.ipdl index 137093f6c982..2d4a761d51c3 100644 --- a/dom/webgpu/ipc/PWebGPU.ipdl +++ b/dom/webgpu/ipc/PWebGPU.ipdl @@ -14,6 +14,7 @@ using SerialPipelineLayoutDescriptor from "mozilla/webgpu/WebGPUTypes.h"; using SerialBindGroupDescriptor from "mozilla/webgpu/WebGPUTypes.h"; using SerialComputePipelineDescriptor from "mozilla/webgpu/WebGPUTypes.h"; using SerialRenderPipelineDescriptor from "mozilla/webgpu/WebGPUTypes.h"; +using SerialSamplerDescriptor from "mozilla/webgpu/WebGPUTypes.h"; using dom::GPURequestAdapterOptions from "mozilla/dom/WebGPUBinding.h"; using dom::GPUDeviceDescriptor from "mozilla/dom/WebGPUBinding.h"; using dom::GPUCommandEncoderDescriptor from "mozilla/dom/WebGPUBinding.h"; @@ -21,12 +22,12 @@ using dom::GPUCommandBufferDescriptor from "mozilla/dom/WebGPUBinding.h"; using dom::GPUPipelineLayoutDescriptor from "mozilla/dom/WebGPUBinding.h"; using webgpu::ffi::WGPUBufferDescriptor from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUTextureDescriptor from "mozilla/webgpu/ffi/wgpu.h"; -using webgpu::ffi::WGPUSamplerDescriptor from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUTextureViewDescriptor from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUBufferCopyView from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUTextureDataLayout from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUTextureCopyView from "mozilla/webgpu/ffi/wgpu.h"; using webgpu::ffi::WGPUExtent3d from "mozilla/webgpu/ffi/wgpu.h"; +using webgpu::ffi::WGPUHostMap from "mozilla/webgpu/ffi/wgpu.h"; include "mozilla/webgpu/WebGPUSerialize.h"; include protocol PCompositorBridge; @@ -48,16 +49,17 @@ parent: async AdapterRequestDevice(RawId selfId, GPUDeviceDescriptor desc, RawId newId); async AdapterDestroy(RawId selfId); async DeviceCreateBuffer(RawId selfId, WGPUBufferDescriptor desc, nsCString label, RawId newId); - async DeviceDestroy(RawId selfId); - async DeviceUnmapBuffer(RawId selfId, RawId bufferId, Shmem shmem, bool flush); - async BufferMapRead(RawId selfId, Shmem shmem) returns (Shmem sm); + async BufferReturnShmem(RawId selfId, Shmem shmem); + async BufferMap(RawId selfId, WGPUHostMap hostMap, uint64_t offset, uint64_t size) returns (Shmem sm); + async BufferUnmap(RawId selfId, Shmem shmem, bool flush); async BufferDestroy(RawId selfId); async DeviceCreateTexture(RawId selfId, WGPUTextureDescriptor desc, nsCString label, RawId newId); async TextureCreateView(RawId selfId, WGPUTextureViewDescriptor desc, nsCString label, RawId newId); async TextureDestroy(RawId selfId); async TextureViewDestroy(RawId selfId); - async DeviceCreateSampler(RawId selfId, WGPUSamplerDescriptor desc, nsCString label, RawId newId); + async DeviceCreateSampler(RawId selfId, SerialSamplerDescriptor desc, RawId newId); async SamplerDestroy(RawId selfId); + async DeviceDestroy(RawId selfId); async DeviceCreateCommandEncoder(RawId selfId, GPUCommandEncoderDescriptor desc, RawId newId); async CommandEncoderCopyBufferToBuffer(RawId selfId, RawId sourceId, BufferAddress sourceOffset, RawId destinationId, BufferAddress destinationOffset, BufferAddress size); @@ -79,7 +81,7 @@ parent: 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 DeviceCreateShaderModule(RawId selfId, uint32_t[] spirv, nsCString wgsl, RawId newId); async ShaderModuleDestroy(RawId selfId); async DeviceCreateComputePipeline(RawId selfId, SerialComputePipelineDescriptor desc, RawId newId); async ComputePipelineDestroy(RawId selfId); diff --git a/dom/webgpu/ipc/WebGPUChild.cpp b/dom/webgpu/ipc/WebGPUChild.cpp index adef123bb38b..2afbe66adf9c 100644 --- a/dom/webgpu/ipc/WebGPUChild.cpp +++ b/dom/webgpu/ipc/WebGPUChild.cpp @@ -49,11 +49,8 @@ RefPtr WebGPUChild::InstanceRequestAdapter( ->Then( GetCurrentSerialEventTarget(), __func__, [](const RawId& aId) { - if (aId == 0) { - return RawIdPromise::CreateAndReject(Nothing(), __func__); - } else { - return RawIdPromise::CreateAndResolve(aId, __func__); - } + return aId == 0 ? RawIdPromise::CreateAndReject(Nothing(), __func__) + : RawIdPromise::CreateAndResolve(aId, __func__); }, [](const ipc::ResponseRejectReason& aReason) { return RawIdPromise::CreateAndReject(Some(aReason), __func__); @@ -65,10 +62,9 @@ Maybe WebGPUChild::AdapterRequestDevice( RawId id = ffi::wgpu_client_make_device_id(mClient, aSelfId); if (SendAdapterRequestDevice(aSelfId, aDesc, id)) { return Some(id); - } else { - ffi::wgpu_client_kill_device_id(mClient, id); - return Nothing(); } + ffi::wgpu_client_kill_device_id(mClient, id); + return Nothing(); } RawId WebGPUChild::DeviceCreateBuffer(RawId aSelfId, @@ -76,6 +72,7 @@ RawId WebGPUChild::DeviceCreateBuffer(RawId aSelfId, ffi::WGPUBufferDescriptor desc = {}; desc.size = aDesc.mSize; desc.usage = aDesc.mUsage; + desc.mapped_at_creation = aDesc.mMappedAtCreation; RawId id = ffi::wgpu_client_make_buffer_id(mClient, aSelfId); if (!SendDeviceCreateBuffer(aSelfId, desc, nsCString(), id)) { @@ -177,23 +174,21 @@ RawId WebGPUChild::TextureCreateView( RawId WebGPUChild::DeviceCreateSampler(RawId aSelfId, const dom::GPUSamplerDescriptor& aDesc) { - ffi::WGPUSamplerDescriptor desc = {}; - desc.address_mode_u = ffi::WGPUAddressMode(aDesc.mAddressModeU); - desc.address_mode_v = ffi::WGPUAddressMode(aDesc.mAddressModeV); - desc.address_mode_w = ffi::WGPUAddressMode(aDesc.mAddressModeW); - desc.mag_filter = ffi::WGPUFilterMode(aDesc.mMagFilter); - desc.min_filter = ffi::WGPUFilterMode(aDesc.mMinFilter); - desc.mipmap_filter = ffi::WGPUFilterMode(aDesc.mMipmapFilter); - desc.lod_min_clamp = aDesc.mLodMinClamp; - desc.lod_max_clamp = aDesc.mLodMaxClamp; - ffi::WGPUCompareFunction compare; + SerialSamplerDescriptor desc = {}; + desc.mAddressU = ffi::WGPUAddressMode(aDesc.mAddressModeU); + desc.mAddressV = ffi::WGPUAddressMode(aDesc.mAddressModeV); + desc.mAddressW = ffi::WGPUAddressMode(aDesc.mAddressModeW); + desc.mMagFilter = ffi::WGPUFilterMode(aDesc.mMagFilter); + desc.mMinFilter = ffi::WGPUFilterMode(aDesc.mMinFilter); + desc.mMipmapFilter = ffi::WGPUFilterMode(aDesc.mMipmapFilter); + desc.mLodMinClamp = aDesc.mLodMinClamp; + desc.mLodMaxClamp = aDesc.mLodMaxClamp; if (aDesc.mCompare.WasPassed()) { - compare = ConvertCompareFunction(aDesc.mCompare.Value()); - desc.compare = compare; + desc.mCompare = Some(ConvertCompareFunction(aDesc.mCompare.Value())); } RawId id = ffi::wgpu_client_make_sampler_id(mClient, aSelfId); - if (!SendDeviceCreateSampler(aSelfId, desc, nsCString(), id)) { + if (!SendDeviceCreateSampler(aSelfId, desc, id)) { MOZ_CRASH("IPC failure"); } return id; @@ -228,7 +223,7 @@ RawId WebGPUChild::DeviceCreateBindGroupLayout( ffi::WGPUBindGroupLayoutEntry e = {}; e.binding = entry.mBinding; e.visibility = entry.mVisibility; - e.ty = ffi::WGPUBindingType(entry.mType); + e.ty = ffi::WGPURawBindingType(entry.mType); e.multisampled = entry.mMultisampled; e.has_dynamic_offset = entry.mHasDynamicOffset; e.view_dimension = ffi::WGPUTextureViewDimension(entry.mViewDimension); @@ -295,12 +290,18 @@ RawId WebGPUChild::DeviceCreateBindGroup( 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.ComputeState(); - nsTArray data(code.Length()); - data.AppendElements(code.Data(), code.Length()); - if (!SendDeviceCreateShaderModule(aSelfId, data, id)) { + + nsTArray spirv; + nsCString wgsl; + if (aDesc.mCode.IsString()) { + CopyUTF16toUTF8(aDesc.mCode.GetAsString(), wgsl); + } else { + const auto& code = aDesc.mCode.GetAsUint32Array(); + code.ComputeState(); + spirv.AppendElements(code.Data(), code.Length()); + } + + if (!SendDeviceCreateShaderModule(aSelfId, spirv, wgsl, id)) { MOZ_CRASH("IPC failure"); } return id; diff --git a/dom/webgpu/ipc/WebGPUChild.h b/dom/webgpu/ipc/WebGPUChild.h index f79815635be2..e68669b174b2 100644 --- a/dom/webgpu/ipc/WebGPUChild.h +++ b/dom/webgpu/ipc/WebGPUChild.h @@ -22,7 +22,6 @@ struct WGPUClient; struct WGPUTextureViewDescriptor; } // namespace ffi -struct TextureInfo; typedef MozPromise, true> RawIdPromise; class WebGPUChild final : public PWebGPUChild { diff --git a/dom/webgpu/ipc/WebGPUParent.cpp b/dom/webgpu/ipc/WebGPUParent.cpp index 572ef51bd1f7..ef2660facd21 100644 --- a/dom/webgpu/ipc/WebGPUParent.cpp +++ b/dom/webgpu/ipc/WebGPUParent.cpp @@ -202,53 +202,94 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateBuffer( desc.label = aLabel.Data(); } ffi::wgpu_server_device_create_buffer(mContext, aSelfId, &desc, aNewId); - return IPC_OK(); -} -ipc::IPCResult WebGPUParent::RecvDeviceUnmapBuffer(RawId aSelfId, - RawId aBufferId, - Shmem&& aShmem, - bool aFlush) { - if (aFlush) { - ffi::wgpu_server_device_set_buffer_sub_data(mContext, aSelfId, aBufferId, 0, - aShmem.get(), - aShmem.Size()); - } else { - ffi::wgpu_server_buffer_unmap(mContext, aBufferId); + if (desc.usage & (WGPUBufferUsage_MAP_READ | WGPUBufferUsage_MAP_WRITE)) { + mSharedMemoryMap.insert({aNewId, Shmem()}); } - DeallocShmem(aShmem); return IPC_OK(); } -struct MapReadRequest { +ipc::IPCResult WebGPUParent::RecvBufferReturnShmem(RawId aSelfId, + Shmem&& aShmem) { + mSharedMemoryMap[aSelfId] = aShmem; + return IPC_OK(); +} + +struct MapRequest { + const ffi::WGPUGlobal* const mContext; + ffi::WGPUBufferId mBufferId; + ffi::WGPUHostMap mHostMap; + uint64_t mOffset; ipc::Shmem mShmem; - WebGPUParent::BufferMapReadResolver mResolver; - MapReadRequest(ipc::Shmem&& shmem, - WebGPUParent::BufferMapReadResolver&& resolver) - : mShmem(shmem), mResolver(resolver) {} + WebGPUParent::BufferMapResolver mResolver; + MapRequest(const ffi::WGPUGlobal* context, ffi::WGPUBufferId bufferId, + ffi::WGPUHostMap hostMap, uint64_t offset, ipc::Shmem&& shmem, + WebGPUParent::BufferMapResolver&& resolver) + : mContext(context), + mBufferId(bufferId), + mHostMap(hostMap), + mOffset(offset), + mShmem(shmem), + mResolver(resolver) {} }; -static void MapReadCallback(ffi::WGPUBufferMapAsyncStatus status, - const uint8_t* ptr, uint8_t* userdata) { - auto req = reinterpret_cast(userdata); +static void MapCallback(ffi::WGPUBufferMapAsyncStatus status, + uint8_t* userdata) { + auto* req = reinterpret_cast(userdata); // TODO: better handle errors MOZ_ASSERT(status == ffi::WGPUBufferMapAsyncStatus_Success); - memcpy(req->mShmem.get(), ptr, req->mShmem.Size()); + if (req->mHostMap == ffi::WGPUHostMap_Read) { + const uint8_t* ptr = ffi::wgpu_server_buffer_get_mapped_range( + req->mContext, req->mBufferId, req->mOffset, + req->mShmem.Size()); + memcpy(req->mShmem.get(), ptr, req->mShmem.Size()); + } req->mResolver(std::move(req->mShmem)); delete req; } -ipc::IPCResult WebGPUParent::RecvBufferMapRead( - RawId aSelfId, Shmem&& aShmem, BufferMapReadResolver&& aResolver) { - auto size = aShmem.Size(); - auto request = new MapReadRequest(std::move(aShmem), std::move(aResolver)); - ffi::wgpu_server_buffer_map_read(mContext, aSelfId, 0, size, &MapReadCallback, - reinterpret_cast(request)); +ipc::IPCResult WebGPUParent::RecvBufferMap(RawId aSelfId, + ffi::WGPUHostMap aHostMap, + uint64_t aOffset, uint64_t aSize, + BufferMapResolver&& aResolver) { + auto* request = new MapRequest(mContext, aSelfId, aHostMap, aOffset, + std::move(mSharedMemoryMap[aSelfId]), + std::move(aResolver)); + ffi::WGPUBufferMapOperation mapOperation = { + aHostMap, &MapCallback, reinterpret_cast(request)}; + ffi::wgpu_server_buffer_map(mContext, aSelfId, aOffset, aSize, mapOperation); + return IPC_OK(); +} + +ipc::IPCResult WebGPUParent::RecvBufferUnmap(RawId aSelfId, Shmem&& aShmem, + bool aFlush) { + if (aFlush) { + // TODO: flush exact modified sub-range + uint8_t* ptr = ffi::wgpu_server_buffer_get_mapped_range( + mContext, aSelfId, 0, aShmem.Size()); + MOZ_ASSERT(ptr != nullptr); + memcpy(ptr, aShmem.get(), aShmem.Size()); + } + + ffi::wgpu_server_buffer_unmap(mContext, aSelfId); + + const auto iter = mSharedMemoryMap.find(aSelfId); + if (iter == mSharedMemoryMap.end()) { + DeallocShmem(aShmem); + } else { + iter->second = aShmem; + } return IPC_OK(); } ipc::IPCResult WebGPUParent::RecvBufferDestroy(RawId aSelfId) { ffi::wgpu_server_buffer_destroy(mContext, aSelfId); + + const auto iter = mSharedMemoryMap.find(aSelfId); + if (iter != mSharedMemoryMap.end()) { + DeallocShmem(iter->second); + mSharedMemoryMap.erase(iter); + } return IPC_OK(); } @@ -285,11 +326,21 @@ ipc::IPCResult WebGPUParent::RecvTextureViewDestroy(RawId aSelfId) { } ipc::IPCResult WebGPUParent::RecvDeviceCreateSampler( - RawId aSelfId, const ffi::WGPUSamplerDescriptor& aDesc, - const nsCString& aLabel, RawId aNewId) { - ffi::WGPUSamplerDescriptor desc = aDesc; - if (!aLabel.IsEmpty()) { - desc.label = aLabel.Data(); + RawId aSelfId, const SerialSamplerDescriptor& aDesc, RawId aNewId) { + ffi::WGPUSamplerDescriptor desc = {}; + desc.address_modes[0] = aDesc.mAddressU; + desc.address_modes[1] = aDesc.mAddressV; + desc.address_modes[2] = aDesc.mAddressW; + desc.mag_filter = aDesc.mMagFilter; + desc.min_filter = aDesc.mMinFilter; + desc.mipmap_filter = aDesc.mMipmapFilter; + desc.lod_min_clamp = aDesc.mLodMinClamp; + desc.lod_max_clamp = aDesc.mLodMaxClamp; + if (aDesc.mCompare) { + desc.compare = aDesc.mCompare.ptr(); + } + if (!aDesc.mLabel.IsEmpty()) { + desc.label = aDesc.mLabel.Data(); } ffi::wgpu_server_device_create_sampler(mContext, aSelfId, &desc, aNewId); return IPC_OK(); @@ -440,27 +491,24 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateBindGroup( RawId aSelfId, const SerialBindGroupDescriptor& aDesc, RawId aNewId) { nsTArray ffiEntries(aDesc.mEntries.Length()); for (const auto& entry : aDesc.mEntries) { - ffi::WGPUBindGroupEntry bgb = {}; - bgb.binding = entry.mBinding; + ffi::WGPUBindGroupEntry bge = {}; + bge.binding = entry.mBinding; switch (entry.mType) { case SerialBindGroupEntryType::Buffer: - bgb.resource.tag = ffi::WGPUBindingResource_Buffer; - bgb.resource.buffer._0.buffer = entry.mValue; - bgb.resource.buffer._0.offset = entry.mBufferOffset; - bgb.resource.buffer._0.size = ffi::make_buffer_size(entry.mBufferSize); + bge.buffer = entry.mValue; + bge.offset = entry.mBufferOffset; + bge.size = ffi::make_buffer_size(entry.mBufferSize); break; case SerialBindGroupEntryType::Texture: - bgb.resource.tag = ffi::WGPUBindingResource_TextureView; - bgb.resource.texture_view._0 = entry.mValue; + bge.texture_view = entry.mValue; break; case SerialBindGroupEntryType::Sampler: - bgb.resource.tag = ffi::WGPUBindingResource_Sampler; - bgb.resource.sampler._0 = entry.mValue; + bge.sampler = entry.mValue; break; default: MOZ_CRASH("unreachable"); } - ffiEntries.AppendElement(bgb); + ffiEntries.AppendElement(bge); } ffi::WGPUBindGroupDescriptor desc = {}; desc.layout = aDesc.mLayout; @@ -476,10 +524,11 @@ ipc::IPCResult WebGPUParent::RecvBindGroupDestroy(RawId aSelfId) { } ipc::IPCResult WebGPUParent::RecvDeviceCreateShaderModule( - RawId aSelfId, const nsTArray& aData, RawId aNewId) { + RawId aSelfId, const nsTArray& aSpirv, const nsCString& aWgsl, + RawId aNewId) { ffi::WGPUShaderModuleDescriptor desc = {}; - desc.code.bytes = aData.Elements(); - desc.code.length = aData.Length(); + desc.code.bytes = aSpirv.Elements(); + desc.code.length = aSpirv.Length(); ffi::wgpu_server_device_create_shader_module(mContext, aSelfId, &desc, aNewId); return IPC_OK(); @@ -578,12 +627,12 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain( NS_ERROR("Invalid total buffer size!"); return IPC_OK(); } - auto textureHostData = new (fallible) uint8_t[wholeBufferSize.value()]; + auto* textureHostData = new (fallible) uint8_t[wholeBufferSize.value()]; if (!textureHostData) { NS_ERROR("Unable to allocate host data!"); return IPC_OK(); } - auto textureHost = new layers::MemoryTextureHost( + RefPtr textureHost = new layers::MemoryTextureHost( textureHostData, aDesc, layers::TextureFlags::NO_FLAGS); textureHost->CreateRenderTexture(aExternalId); nsTArray bufferIds(aBufferIds.Clone()); @@ -603,28 +652,39 @@ ipc::IPCResult WebGPUParent::RecvDeviceCreateSwapChain( return IPC_OK(); } +struct PresentRequest { + const ffi::WGPUGlobal* mContext; + RefPtr mData; +}; + static void PresentCallback(ffi::WGPUBufferMapAsyncStatus status, - const uint8_t* ptr, uint8_t* userdata) { - auto data = reinterpret_cast(userdata); + uint8_t* userdata) { + auto* req = reinterpret_cast(userdata); + PresentationData* data = req->mData.get(); + // get the buffer ID + data->mBuffersLock.Lock(); + RawId bufferId = data->mQueuedBufferIds.back(); + data->mQueuedBufferIds.pop_back(); + data->mAvailableBufferIds.push_back(bufferId); + data->mBuffersLock.Unlock(); + // copy the data if (status == ffi::WGPUBufferMapAsyncStatus_Success) { + const auto bufferSize = data->mRowCount * data->mSourcePitch; + const uint8_t* ptr = ffi::wgpu_server_buffer_get_mapped_range( + req->mContext, bufferId, 0, bufferSize); uint8_t* dst = data->mTextureHost->GetBuffer(); for (uint32_t row = 0; row < data->mRowCount; ++row) { memcpy(dst, ptr, data->mTargetPitch); dst += data->mTargetPitch; ptr += data->mSourcePitch; } + wgpu_server_buffer_unmap(req->mContext, bufferId); } else { // TODO: better handle errors NS_WARNING("WebGPU frame mapping failed!"); } - data->mBuffersLock.Lock(); - RawId bufferId = data->mQueuedBufferIds.back(); - data->mQueuedBufferIds.pop_back(); - data->mAvailableBufferIds.push_back(bufferId); - data->mBuffersLock.Unlock(); - // We artificially did `AddRef` before calling `wgpu_server_buffer_map_read`. - // Now we can let it go again. - data->Release(); + // free yourself + delete req; } ipc::IPCResult WebGPUParent::RecvSwapChainPresent( @@ -645,7 +705,6 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent( data->mBuffersLock.Lock(); if (!data->mAvailableBufferIds.empty()) { bufferId = data->mAvailableBufferIds.back(); - wgpu_server_buffer_unmap(mContext, bufferId); data->mAvailableBufferIds.pop_back(); } else if (!data->mUnassignedBufferIds.empty()) { bufferId = data->mUnassignedBufferIds.back(); @@ -703,13 +762,15 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent( // texture, // we can just give it the contents of the last mapped buffer instead of the // copy. - // This `AddRef` is needed for passing `data` as a raw pointer to - // `wgpu_server_buffer_map_read` to serve as `userdata`. It's released at - // the end of `PresentCallback` body. - const auto userData = do_AddRef(data).take(); - ffi::wgpu_server_buffer_map_read(mContext, bufferId, 0, bufferSize, - &PresentCallback, - reinterpret_cast(userData)); + auto* const presentRequest = new PresentRequest{ + mContext, + data, + }; + + ffi::WGPUBufferMapOperation mapOperation = { + ffi::WGPUHostMap_Read, &PresentCallback, + reinterpret_cast(presentRequest)}; + ffi::wgpu_server_buffer_map(mContext, bufferId, 0, bufferSize, mapOperation); return IPC_OK(); } diff --git a/dom/webgpu/ipc/WebGPUParent.h b/dom/webgpu/ipc/WebGPUParent.h index 05e308778e60..a2f919650737 100644 --- a/dom/webgpu/ipc/WebGPUParent.h +++ b/dom/webgpu/ipc/WebGPUParent.h @@ -33,10 +33,11 @@ class WebGPUParent final : public PWebGPUParent { ipc::IPCResult RecvDeviceCreateBuffer(RawId aSelfId, const ffi::WGPUBufferDescriptor& aDesc, const nsCString& aLabel, RawId aNewId); - ipc::IPCResult RecvDeviceUnmapBuffer(RawId aSelfId, RawId aBufferId, - Shmem&& aShmem, bool aFlush); - ipc::IPCResult RecvBufferMapRead(RawId aSelfId, Shmem&& aShmem, - BufferMapReadResolver&& aResolver); + ipc::IPCResult RecvBufferReturnShmem(RawId aSelfId, Shmem&& aShmem); + ipc::IPCResult RecvBufferMap(RawId aSelfId, ffi::WGPUHostMap aHostMap, + uint64_t aOffset, uint64_t size, + BufferMapResolver&& aResolver); + ipc::IPCResult RecvBufferUnmap(RawId aSelfId, Shmem&& aShmem, bool aFlush); ipc::IPCResult RecvBufferDestroy(RawId aSelfId); ipc::IPCResult RecvDeviceCreateTexture( RawId aSelfId, const ffi::WGPUTextureDescriptor& aDesc, @@ -46,9 +47,9 @@ class WebGPUParent final : public PWebGPUParent { const nsCString& aLabel, RawId aNewId); ipc::IPCResult RecvTextureDestroy(RawId aSelfId); ipc::IPCResult RecvTextureViewDestroy(RawId aSelfId); - ipc::IPCResult RecvDeviceCreateSampler( - RawId aSelfId, const ffi::WGPUSamplerDescriptor& aDesc, - const nsCString& aLabel, RawId aNewId); + ipc::IPCResult RecvDeviceCreateSampler(RawId aSelfId, + const SerialSamplerDescriptor& aDesc, + RawId aNewId); ipc::IPCResult RecvSamplerDestroy(RawId aSelfId); ipc::IPCResult RecvDeviceCreateCommandEncoder( RawId aSelfId, const dom::GPUCommandEncoderDescriptor& aDesc, @@ -92,7 +93,8 @@ class WebGPUParent final : public PWebGPUParent { RawId aSelfId, const SerialBindGroupDescriptor& aDesc, RawId aNewId); ipc::IPCResult RecvBindGroupDestroy(RawId aSelfId); ipc::IPCResult RecvDeviceCreateShaderModule(RawId aSelfId, - const nsTArray& aData, + const nsTArray& aSpirv, + const nsCString& aWgsl, RawId aNewId); ipc::IPCResult RecvShaderModuleDestroy(RawId aSelfId); ipc::IPCResult RecvDeviceCreateComputePipeline( @@ -116,8 +118,13 @@ class WebGPUParent final : public PWebGPUParent { virtual ~WebGPUParent(); void MaintainDevices(); - const ffi::WGPUGlobal_IdentityRecyclerFactory* const mContext; + const ffi::WGPUGlobal* const mContext; base::RepeatingTimer mTimer; + /// Shmem associated with a mappable buffer has to be owned by one of the + /// processes. We keep it here for every mappable buffer while the buffer is + /// used by GPU. + std::unordered_map mSharedMemoryMap; + /// Associated presentation data for each swapchain. std::unordered_map> mCanvasMap; }; diff --git a/dom/webgpu/ipc/WebGPUSerialize.h b/dom/webgpu/ipc/WebGPUSerialize.h index 85b176f55508..27531f81c76f 100644 --- a/dom/webgpu/ipc/WebGPUSerialize.h +++ b/dom/webgpu/ipc/WebGPUSerialize.h @@ -48,19 +48,19 @@ DEFINE_IPC_SERIALIZER_DOM_ENUM(mozilla::dom::GPUPowerPreference); DEFINE_IPC_SERIALIZER_DOM_ENUM(mozilla::webgpu::SerialBindGroupEntryType); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUAddressMode); -DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUBindingType); +DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPURawBindingType); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUBlendFactor); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUBlendOperation); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUCompareFunction); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUCullMode); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUFilterMode); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUFrontFace); +DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUHostMap); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUIndexFormat); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUInputStepMode); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUPrimitiveTopology); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUStencilOperation); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUTextureAspect); -DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUTextureComponentType); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUTextureDimension); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUTextureFormat); DEFINE_IPC_SERIALIZER_FFI_ENUM(mozilla::webgpu::ffi::WGPUTextureViewDimension); @@ -77,15 +77,10 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::GPULimits, mMaxBindGroups); DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::GPUDeviceDescriptor, mExtensions, mLimits); DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::ffi::WGPUBufferDescriptor, - label, size, usage); + label, size, usage, mapped_at_creation); DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::ffi::WGPUTextureDescriptor, label, size, mip_level_count, sample_count, dimension, format, usage); -DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::ffi::WGPUSamplerDescriptor, - label, address_mode_u, address_mode_v, - address_mode_w, mag_filter, min_filter, - mipmap_filter, lod_min_clamp, lod_max_clamp, - compare, anisotropy_clamp); DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::ffi::WGPUExtent3d, width, height, depth); DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::ffi::WGPUOrigin3d, x, y, z); @@ -146,6 +141,11 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS( mFragmentStage, mPrimitiveTopology, mRasterizationState, mColorStates, mDepthStencilState, mVertexState, mSampleCount, mSampleMask, mAlphaToCoverageEnabled); +DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::webgpu::SerialSamplerDescriptor, + mLabel, mAddressU, mAddressV, mAddressW, + mMagFilter, mMinFilter, mMipmapFilter, + mLodMinClamp, mLodMaxClamp, mCompare, + mAnisotropyClamp); #undef DEFINE_IPC_SERIALIZER_FFI_ENUM #undef DEFINE_IPC_SERIALIZER_DOM_ENUM diff --git a/dom/webgpu/ipc/WebGPUTypes.h b/dom/webgpu/ipc/WebGPUTypes.h index de00f5e91746..206e00607cd8 100644 --- a/dom/webgpu/ipc/WebGPUTypes.h +++ b/dom/webgpu/ipc/WebGPUTypes.h @@ -34,52 +34,66 @@ enum class SerialBindGroupEntryType : uint8_t { }; struct SerialBindGroupEntry { - uint32_t mBinding; - SerialBindGroupEntryType mType; - RawId mValue; - BufferAddress mBufferOffset; - BufferAddress mBufferSize; + uint32_t mBinding = 0; + SerialBindGroupEntryType mType = SerialBindGroupEntryType::EndGuard_; + RawId mValue = 0; + BufferAddress mBufferOffset = 0; + BufferAddress mBufferSize = 0; }; struct SerialBindGroupDescriptor { nsCString mLabel; - RawId mLayout; + RawId mLayout = 0; nsTArray mEntries; }; struct SerialProgrammableStageDescriptor { - RawId mModule; + RawId mModule = 0; nsString mEntryPoint; }; struct SerialComputePipelineDescriptor { - RawId mLayout; + RawId mLayout = 0; SerialProgrammableStageDescriptor mComputeStage; }; struct SerialVertexBufferLayoutDescriptor { - ffi::WGPUBufferAddress mArrayStride; - ffi::WGPUInputStepMode mStepMode; + ffi::WGPUBufferAddress mArrayStride = 0; + ffi::WGPUInputStepMode mStepMode = ffi::WGPUInputStepMode_Sentinel; nsTArray mAttributes; }; struct SerialVertexStateDescriptor { - ffi::WGPUIndexFormat mIndexFormat; + ffi::WGPUIndexFormat mIndexFormat = ffi::WGPUIndexFormat_Sentinel; nsTArray mVertexBuffers; }; struct SerialRenderPipelineDescriptor { - RawId mLayout; + RawId mLayout = 0; SerialProgrammableStageDescriptor mVertexStage; SerialProgrammableStageDescriptor mFragmentStage; - ffi::WGPUPrimitiveTopology mPrimitiveTopology; + ffi::WGPUPrimitiveTopology mPrimitiveTopology = + ffi::WGPUPrimitiveTopology_Sentinel; Maybe mRasterizationState; nsTArray mColorStates; Maybe mDepthStencilState; SerialVertexStateDescriptor mVertexState; - uint32_t mSampleCount; - uint32_t mSampleMask; - bool mAlphaToCoverageEnabled; + uint32_t mSampleCount = 0; + uint32_t mSampleMask = 0; + bool mAlphaToCoverageEnabled = false; +}; + +struct SerialSamplerDescriptor { + nsCString mLabel; + ffi::WGPUAddressMode mAddressU = ffi::WGPUAddressMode_Sentinel, + mAddressV = ffi::WGPUAddressMode_Sentinel, + mAddressW = ffi::WGPUAddressMode_Sentinel; + ffi::WGPUFilterMode mMagFilter = ffi::WGPUFilterMode_Sentinel, + mMinFilter = ffi::WGPUFilterMode_Sentinel, + mMipmapFilter = ffi::WGPUFilterMode_Sentinel; + float mLodMinClamp = 0.0, mLodMaxClamp = 0.0; + Maybe mCompare; + uint8_t mAnisotropyClamp = 0; }; } // namespace webgpu diff --git a/dom/webgpu/mochitest/test_buffer_mapping.html b/dom/webgpu/mochitest/test_buffer_mapping.html index 5e38132107d3..b23fa7e9a654 100644 --- a/dom/webgpu/mochitest/test_buffer_mapping.html +++ b/dom/webgpu/mochitest/test_buffer_mapping.html @@ -13,15 +13,21 @@ ok(SpecialPowers.getBoolPref('dom.webgpu.enabled'), 'Pref should be enabled.'); const func = async function() { const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); - const [buffer, mapping] = await device.createBufferMapped({ - size: 4, - usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_SRC, //TODO: remove the dummy usage - }); - new Float32Array(mapping).set([1.0]); - buffer.unmap(); - const data = await buffer.mapReadAsync(); + + const bufferRead = device.createBuffer({ size:4, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST }); + const bufferWrite = device.createBuffer({ size:4, usage: GPUBufferUsage.COPY_SRC, mappedAtCreation: true }); + (new Float32Array(bufferWrite.getMappedRange())).set([1.0]); + bufferWrite.unmap(); + + const encoder = device.createCommandEncoder(); + encoder.copyBufferToBuffer(bufferWrite, 0, bufferRead, 0, 4); + device.defaultQueue.submit([encoder.finish()]); + + await bufferRead.mapAsync(GPUMapMode.READ); + const data = bufferRead.getMappedRange(); const value = new Float32Array(data)[0]; - buffer.unmap(); + bufferRead.unmap(); + ok(value == 1.0, 'value == 1.0'); }; diff --git a/dom/webidl/WebGPU.webidl b/dom/webidl/WebGPU.webidl index 1170b3651609..dbff4d970695 100644 --- a/dom/webidl/WebGPU.webidl +++ b/dom/webidl/WebGPU.webidl @@ -125,10 +125,8 @@ interface GPUDevice { [SameObject] readonly attribute GPUQueue defaultQueue; - [NewObject] - GPUBuffer createBuffer(GPUBufferDescriptor descriptor); [NewObject, Throws] - GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor); + GPUBuffer createBuffer(GPUBufferDescriptor descriptor); [NewObject] GPUTexture createTexture(GPUTextureDescriptor descriptor); [NewObject] @@ -219,14 +217,26 @@ interface GPUBufferUsage { dictionary GPUBufferDescriptor { required GPUSize64 size; required GPUBufferUsageFlags usage; + boolean mappedAtCreation = false; +}; + +typedef unsigned long GPUMapModeFlags; + +[Pref="dom.webgpu.enabled", + Exposed=Window] +interface GPUMapMode + { + const GPUMapModeFlags READ = 0x0001; + const GPUMapModeFlags WRITE = 0x0002; }; [Pref="dom.webgpu.enabled", Exposed=Window] interface GPUBuffer { [NewObject] - Promise mapReadAsync(); - //Promise mapWriteAsync(); + Promise mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size); + [NewObject, Throws] + ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size); [Throws] void unmap(); diff --git a/gfx/wgpu/Cargo.lock b/gfx/wgpu/Cargo.lock index d8e0b8777cc5..0f44284d3615 100644 --- a/gfx/wgpu/Cargo.lock +++ b/gfx/wgpu/Cargo.lock @@ -24,10 +24,10 @@ dependencies = [ ] [[package]] -name = "android_glue" -version = "0.2.3" +name = "android_log-sys" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" +checksum = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e" [[package]] name = "approx" @@ -46,11 +46,11 @@ checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "ash" -version = "0.31.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38" +checksum = "69daec0742947f33a85931fa3cb0ce5f07929159dcbd1f0cbb5b2912e2978509" dependencies = [ - "libloading 0.6.1", + "libloading 0.5.2", ] [[package]] @@ -113,9 +113,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bumpalo" -version = "3.2.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "byteorder" @@ -136,9 +136,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.52" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" +checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" [[package]] name = "cfg-if" @@ -157,39 +157,24 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.19.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400" +checksum = "8f7b6f3f7f4f0b3ec5c5039aaa9e8c3cef97a7a480a400fd62944841314f293d" dependencies = [ "bitflags", "block", - "core-foundation 0.6.4", + "core-foundation 0.7.0", "core-graphics", "foreign-types", "libc", "objc", ] -[[package]] -name = "cocoa-foundation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.0", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - [[package]] name = "copyless" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" +checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" [[package]] name = "core-foundation" @@ -203,11 +188,11 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5ed8e7e76c45974e15e41bfa8d5b0483cd90191639e01d8f5f1e606299d3fb" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" dependencies = [ - "core-foundation-sys 0.8.0", + "core-foundation-sys 0.7.0", "libc", ] @@ -219,42 +204,30 @@ checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" [[package]] name = "core-foundation-sys" -version = "0.8.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "core-graphics" -version = "0.17.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" +checksum = "59e78b2e0aaf43f08e7ae0d6bc96895ef72ff0921c7d4ff4762201b2dba376dd" dependencies = [ "bitflags", - "core-foundation 0.6.4", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e92f5d519093a4178296707dbaa3880eae85a5ef5386675f361a1cf25376e93c" -dependencies = [ - "bitflags", - "core-foundation 0.9.0", + "core-foundation 0.7.0", "foreign-types", "libc", ] [[package]] name = "core-video-sys" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc065219542086f72d1e9f7aadbbab0989e980263695d129d502082d063a9d0" +checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" dependencies = [ "cfg-if", - "core-foundation-sys 0.6.2", + "core-foundation-sys 0.7.0", "core-graphics", "libc", "objc", @@ -271,6 +244,17 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "derivative" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" +dependencies = [ + "proc-macro2 1.0.18", + "quote 1.0.7", + "syn", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -279,11 +263,11 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dlib" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" +checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" dependencies = [ - "libloading 0.5.2", + "libloading 0.6.2", ] [[package]] @@ -367,17 +351,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "gfx-auxil" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b46e6f0031330a0be08d17820f2dcaaa91cb36710a97a9500cb4f1c36e785c8" -dependencies = [ - "fxhash", - "gfx-hal", - "spirv_cross 0.18.0", -] - [[package]] name = "gfx-auxil" version = "0.4.0" @@ -386,17 +359,17 @@ checksum = "67bdbf8e8d6883c70e5a0d7379ad8ab3ac95127a3761306b36122d8f1c177a8e" dependencies = [ "fxhash", "gfx-hal", - "spirv_cross 0.20.0", + "spirv_cross", ] [[package]] name = "gfx-backend-dx11" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b148219292624126f78245e50a9720d95ea149a415ce8ce73ab7014205301b88" +checksum = "92de0ddc0fde1a89b2a0e92dcc6bbb554bd34af0135e53a28d5ef064611094a4" dependencies = [ "bitflags", - "gfx-auxil 0.3.0", + "gfx-auxil", "gfx-hal", "libloading 0.5.2", "log", @@ -404,26 +377,26 @@ dependencies = [ "range-alloc", "raw-window-handle", "smallvec", - "spirv_cross 0.18.0", + "spirv_cross", "winapi 0.3.8", "wio", ] [[package]] name = "gfx-backend-dx12" -version = "0.5.0" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0e526746379e974501551b08958947e67a81b5ea8cdc717a000cdd72577da05" +checksum = "98c598fb38d6f51db0219ac26d16ff8b78bc134987acd1940438a5adc46b694f" dependencies = [ "bitflags", "d3d12", - "gfx-auxil 0.3.0", + "gfx-auxil", "gfx-hal", "log", "range-alloc", "raw-window-handle", "smallvec", - "spirv_cross 0.18.0", + "spirv_cross", "winapi 0.3.8", ] @@ -439,17 +412,18 @@ dependencies = [ [[package]] name = "gfx-backend-metal" -version = "0.5.6" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92804d20b194de6c84cb4bec14ec6a6dcae9c51f0a9186817fb412a590131ae6" +checksum = "7264b73ea2d8a7cff7eec3a4d08028a96cc18ff2fdf6479fb6f7febbc97dd03f" dependencies = [ "arrayvec", "bitflags", "block", - "cocoa-foundation", + "cocoa", "copyless", + "core-graphics", "foreign-types", - "gfx-auxil 0.4.0", + "gfx-auxil", "gfx-hal", "lazy_static", "log", @@ -459,20 +433,20 @@ dependencies = [ "range-alloc", "raw-window-handle", "smallvec", - "spirv_cross 0.20.0", + "spirv_cross", "storage-map", ] [[package]] name = "gfx-backend-vulkan" -version = "0.5.11" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec9c919cfc236d2c36aaa38609c1906a92f2df99a3c7f53022b01936f98275a" +checksum = "5a4614727b750d62766db20d94032833f7293f9307f1b2103d5f8833889f863f" dependencies = [ "arrayvec", "ash", "byteorder", - "core-graphics-types", + "core-graphics", "gfx-hal", "lazy_static", "log", @@ -496,9 +470,9 @@ dependencies = [ [[package]] name = "gfx-hal" -version = "0.5.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18534b23d4c262916231511309bc1f307c74cda8dcb68b93a10ca213a22814b" +checksum = "1036da3617426192c1e8453ed2a2b6a66cf1e8c1486a921e9a8d6625234bf53c" dependencies = [ "bitflags", "raw-window-handle", @@ -519,9 +493,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" dependencies = [ "libc", ] @@ -546,9 +520,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7152d2aed88aa566e7a342250f21ba2222c1ae230ad577499dbfa3c18475b80" +checksum = "7777a24a1ce5de49fcdde84ec46efa487c3af49d5b6e6e0a50367cc5c1096182" [[package]] name = "iovec" @@ -560,10 +534,16 @@ dependencies = [ ] [[package]] -name = "js-sys" -version = "0.3.37" +name = "jni-sys" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce10c23ad2ea25ceca0093bd3192229da4c5b3c0f2de499c1ecac0d98d452177" dependencies = [ "wasm-bindgen", ] @@ -592,9 +572,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.69" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" +checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" [[package]] name = "libloading" @@ -608,9 +588,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c4f51b790f5bdb65acb4cc94bb81d7b2ee60348a5431ac1467d390b017600b0" +checksum = "2cadb8e769f070c45df05c78c7520eb4cd17061d4ab262e43cfc68b4d00ac71c" dependencies = [ "winapi 0.3.8", ] @@ -695,13 +675,14 @@ dependencies = [ [[package]] name = "metal" -version = "0.20.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4e8a431536529327e28c9ba6992f2cb0c15d4222f0602a16e6d7695ff3bccf" +checksum = "e198a0ee42bdbe9ef2c09d0b9426f3b2b47d90d93a4a9b0395c4cea605e92dc0" dependencies = [ "bitflags", "block", - "cocoa-foundation", + "cocoa", + "core-graphics", "foreign-types", "log", "objc", @@ -709,9 +690,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ "cfg-if", "fuchsia-zircon", @@ -763,10 +744,41 @@ dependencies = [ ] [[package]] -name = "net2" -version = "0.2.33" +name = "ndk" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +checksum = "95a356cafe20aee088789830bfea3a61336e84ded9e545e00d3869ce95dcb80c" +dependencies = [ + "jni-sys", + "ndk-sys", + "num_enum", +] + +[[package]] +name = "ndk-glue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1730ee2e3de41c3321160a6da815f008c4006d71b095880ea50e17cf52332b8" +dependencies = [ + "android_log-sys", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-sys", +] + +[[package]] +name = "ndk-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2820aca934aba5ed91c79acc72b6a44048ceacc5d36c035ed4e051f12d887d" + +[[package]] +name = "net2" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" dependencies = [ "cfg-if", "libc", @@ -808,6 +820,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.18", + "quote 1.0.7", + "syn", +] + [[package]] name = "objc" version = "0.2.7" @@ -829,9 +863,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" [[package]] name = "ordered-float" @@ -881,8 +915,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb44a25c5bba983be0fc8592dfaf3e6d0935ce8be0c6b15b2a39507af34a926" dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "syn", "synstructure", "unicode-xid 0.2.0", @@ -915,6 +949,15 @@ dependencies = [ "winit", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro2" version = "0.4.30" @@ -926,9 +969,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" dependencies = [ "unicode-xid 0.2.0", ] @@ -950,18 +993,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.10", + "proc-macro2 1.0.18", ] [[package]] name = "range-alloc" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5927936723a9e8b715d37d7e4b390455087c4bdf25b9f702309460577b14f9" +checksum = "a871f1e45a3a3f0c73fb60343c811238bb5143a81642e27c2ac7aac27ff01a63" [[package]] name = "raw-window-handle" @@ -980,9 +1023,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.3.7" +version = "1.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" dependencies = [ "aho-corasick", "memchr", @@ -992,9 +1035,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" [[package]] name = "renderdoc" @@ -1004,7 +1047,7 @@ checksum = "9c9e8488c98756911664c8cc7b86284c320b6a6357d95908458136d7ebe9280c" dependencies = [ "bitflags", "float-cmp", - "libloading 0.6.1", + "libloading 0.6.2", "once_cell", "renderdoc-sys", "winapi 0.3.8", @@ -1095,21 +1138,21 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.106" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.106" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "syn", ] @@ -1141,17 +1184,6 @@ dependencies = [ "wayland-protocols", ] -[[package]] -name = "spirv_cross" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "946216f8793f7199e3ea5b995ee8dc20a0ace1fcf46293a0ef4c17e1d046dbde" -dependencies = [ - "cc", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "spirv_cross" version = "0.20.0" @@ -1193,23 +1225,23 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.18" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" +checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "unicode-xid 0.2.0", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "syn", "unicode-xid 0.2.0", ] @@ -1232,6 +1264,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +dependencies = [ + "serde", +] + [[package]] name = "typenum" version = "1.12.0" @@ -1262,9 +1303,9 @@ dependencies = [ [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "void" @@ -1285,9 +1326,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.60" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +checksum = "4c2dc4aa152834bc334f506c1a06b866416a8b6697d5c9f75b9a689c8486def0" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1295,37 +1336,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.60" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +checksum = "ded84f06e0ed21499f6184df0e0cb3494727b0c5da89534e0fcc55c51d812101" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.60" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +checksum = "838e423688dac18d73e31edce74ddfac468e37b1506ad163ffaf0a46f703ffe3" dependencies = [ - "quote 1.0.3", + "quote 1.0.7", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.60" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +checksum = "3156052d8ec77142051a533cdd686cba889537b213f948cd1d20869926e68e92" dependencies = [ - "proc-macro2 1.0.10", - "quote 1.0.3", + "proc-macro2 1.0.18", + "quote 1.0.7", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -1333,9 +1374,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.60" +version = "0.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +checksum = "c9ba19973a58daf4db6f352eda73dc0e289493cd29fb2632eb172085b6521acd" [[package]] name = "wayland-client" @@ -1482,14 +1523,13 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winit" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc53342d3d1a3d57f3949e0692d93d5a8adb7814d8683cef4a09c2b550e94246" +checksum = "1e4ccbf7ddb6627828eace16cacde80fc6bf4dbb3469f88487262a02cf8e7862" dependencies = [ - "android_glue", "bitflags", "cocoa", - "core-foundation 0.6.4", + "core-foundation 0.7.0", "core-graphics", "core-video-sys", "dispatch", @@ -1499,6 +1539,9 @@ dependencies = [ "log", "mio", "mio-extras", + "ndk", + "ndk-glue", + "ndk-sys", "objc", "parking_lot", "percent-encoding", diff --git a/gfx/wgpu/README.md b/gfx/wgpu/README.md index b70297c6418a..a327c97dac05 100644 --- a/gfx/wgpu/README.md +++ b/gfx/wgpu/README.md @@ -4,7 +4,7 @@ This is an active GitHub mirror of the WebGPU implementation in Rust, which now # WebGPU -[![Matrix](https://img.shields.io/badge/Matrix-%23wgpu%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#wgpu:matrix.org) +[![Matrix](https://img.shields.io/badge/Dev_Matrix-%23wgpu%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#wgpu:matrix.org) [![Matrix](https://img.shields.io/badge/User_Matrix-%23wgpu--users%3Amatrix.org-blueviolet.svg)](https://matrix.to/#/#wgpu-users:matrix.org) [![Build Status](https://github.com/gfx-rs/wgpu/workflows/CI/badge.svg)](https://github.com/gfx-rs/wgpu/actions) This is the core logic of an experimental [WebGPU](https://www.w3.org/community/gpu/) implementation. It's written in Rust and is based on [gfx-hal](https://github.com/gfx-rs/gfx) with help of [gfx-extras](https://github.com/gfx-rs/gfx-extras). See the upstream [WebGPU specification](https://gpuweb.github.io/gpuweb/) (work in progress). diff --git a/gfx/wgpu/player/src/main.rs b/gfx/wgpu/player/src/main.rs index e4638f32d5d7..3d360eebab35 100644 --- a/gfx/wgpu/player/src/main.rs +++ b/gfx/wgpu/player/src/main.rs @@ -254,16 +254,15 @@ impl GlobalExt for wgc::hub::Global { } } A::CreateBindGroupLayout { id, label, entries } => { - let label = Label::new(&label); self.device_create_bind_group_layout::( device, - &wgc::binding_model::BindGroupLayoutDescriptor { - label: label.as_ptr(), - entries: entries.as_ptr(), - entries_length: entries.len(), + &wgt::BindGroupLayoutDescriptor { + label: Some(&label), + bindings: &entries, }, id, - ); + ) + .unwrap(); } A::DestroyBindGroupLayout(id) => { self.bind_group_layout_destroy::(id); @@ -280,7 +279,8 @@ impl GlobalExt for wgc::hub::Global { bind_group_layouts_length: bind_group_layouts.len(), }, id, - ); + ) + .unwrap(); } A::DestroyPipelineLayout(id) => { self.pipeline_layout_destroy::(id); @@ -292,12 +292,11 @@ impl GlobalExt for wgc::hub::Global { entries, } => { use wgc::binding_model as bm; - let label = Label::new(&label); let entry_vec = entries - .into_iter() + .iter() .map(|(binding, res)| wgc::binding_model::BindGroupEntry { - binding, - resource: match res { + binding: *binding, + resource: match *res { trace::BindingResource::Buffer { id, offset, size } => { bm::BindingResource::Buffer(bm::BufferBinding { buffer: id, @@ -309,6 +308,9 @@ impl GlobalExt for wgc::hub::Global { trace::BindingResource::TextureView(id) => { bm::BindingResource::TextureView(id) } + trace::BindingResource::TextureViewArray(ref id_array) => { + bm::BindingResource::TextureViewArray(id_array) + } }, }) .collect::>(); @@ -316,10 +318,9 @@ impl GlobalExt for wgc::hub::Global { self.device_create_bind_group::( device, &wgc::binding_model::BindGroupDescriptor { - label: label.as_ptr(), + label: Some(&label), layout: layout_id, - entries: entry_vec.as_ptr(), - entries_length: entry_vec.len(), + bindings: &entry_vec, }, id, ); @@ -353,7 +354,8 @@ impl GlobalExt for wgc::hub::Global { compute_stage: cs_stage.desc, }, id, - ); + ) + .unwrap(); } A::DestroyComputePipeline(id) => { self.compute_pipeline_destroy::(id); @@ -400,7 +402,8 @@ impl GlobalExt for wgc::hub::Global { alpha_to_coverage_enabled: desc.alpha_to_coverage_enabled, }, id, - ); + ) + .unwrap(); } A::DestroyRenderPipeline(id) => { self.render_pipeline_destroy::(id); @@ -497,6 +500,7 @@ fn main() { #[cfg(not(feature = "winit"))] compatible_surface: None, }, + unsafe { wgt::UnsafeExtensions::allow() }, wgc::instance::AdapterInputs::IdSet( &[wgc::id::TypedId::zip(0, 0, backend)], |id| id.backend(), diff --git a/gfx/wgpu/wgpu-core/Cargo.toml b/gfx/wgpu/wgpu-core/Cargo.toml index cee2de939aeb..a286c709e7a5 100644 --- a/gfx/wgpu/wgpu-core/Cargo.toml +++ b/gfx/wgpu/wgpu-core/Cargo.toml @@ -27,7 +27,7 @@ bitflags = "1.0" copyless = "0.1" fxhash = "0.2" log = "0.4" -hal = { package = "gfx-hal", version = "0.5" } +hal = { package = "gfx-hal", version = "0.5.1" } gfx-backend-empty = "0.5" gfx-descriptor = "0.1" gfx-memory = "0.1" @@ -51,16 +51,16 @@ version = "0.5" features = ["peek-poke"] [target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies] -gfx-backend-metal = { version = "0.5.6" } -gfx-backend-vulkan = { version = "0.5.11", optional = true } +gfx-backend-metal = { version = "0.5.3" } +gfx-backend-vulkan = { version = "0.5.7", optional = true } [target.'cfg(all(unix, not(target_os = "ios"), not(target_os = "macos")))'.dependencies] -gfx-backend-vulkan = { version = "0.5.11" } +gfx-backend-vulkan = { version = "0.5.7" } [target.'cfg(windows)'.dependencies] -gfx-backend-dx12 = { version = "0.5" } +gfx-backend-dx12 = { version = "0.5.5" } gfx-backend-dx11 = { version = "0.5" } -gfx-backend-vulkan = { version = "0.5.11" } +gfx-backend-vulkan = { version = "0.5.7" } [target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "dragonfly", target_os = "freebsd"))'.dependencies] battery = { version = "0.7", optional = true } diff --git a/gfx/wgpu/wgpu-core/src/binding_model.rs b/gfx/wgpu/wgpu-core/src/binding_model.rs index dc726c32211a..74ed59bf0528 100644 --- a/gfx/wgpu/wgpu-core/src/binding_model.rs +++ b/gfx/wgpu/wgpu-core/src/binding_model.rs @@ -17,50 +17,24 @@ use serde::Deserialize; use serde::Serialize; use std::borrow::Borrow; -#[repr(C)] -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] -#[cfg_attr(feature = "trace", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub enum BindingType { - UniformBuffer = 0, - StorageBuffer = 1, - ReadonlyStorageBuffer = 2, - Sampler = 3, - ComparisonSampler = 4, - SampledTexture = 5, - ReadonlyStorageTexture = 6, - WriteonlyStorageTexture = 7, +#[derive(Clone, Debug)] +pub enum BindGroupLayoutError { + ConflictBinding(u32), + MissingExtension(wgt::Extensions), + /// Arrays of bindings can't be 0 elements long + ZeroCount, + /// Arrays of bindings unsupported for this type of binding + ArrayUnsupported, } -#[repr(C)] -#[derive(Clone, Debug, Hash, PartialEq)] -#[cfg_attr(feature = "trace", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct BindGroupLayoutEntry { - pub binding: u32, - pub visibility: wgt::ShaderStage, - pub ty: BindingType, - pub multisampled: bool, - pub has_dynamic_offset: bool, - pub view_dimension: wgt::TextureViewDimension, - pub texture_component_type: wgt::TextureComponentType, - pub storage_texture_format: wgt::TextureFormat, -} - -#[repr(C)] -#[derive(Debug)] -pub struct BindGroupLayoutDescriptor { - pub label: *const std::os::raw::c_char, - pub entries: *const BindGroupLayoutEntry, - pub entries_length: usize, -} +pub(crate) type BindEntryMap = FastHashMap; #[derive(Debug)] pub struct BindGroupLayout { pub(crate) raw: B::DescriptorSetLayout, pub(crate) device_id: Stored, pub(crate) life_guard: LifeGuard, - pub(crate) entries: FastHashMap, + pub(crate) entries: BindEntryMap, pub(crate) desc_counts: DescriptorCounts, pub(crate) dynamic_count: usize, } @@ -72,6 +46,11 @@ pub struct PipelineLayoutDescriptor { pub bind_group_layouts_length: usize, } +#[derive(Clone, Debug)] +pub enum PipelineLayoutError { + TooManyGroups(usize), +} + #[derive(Debug)] pub struct PipelineLayout { pub(crate) raw: B::PipelineLayout, @@ -90,32 +69,28 @@ pub struct BufferBinding { pub size: wgt::BufferSize, } -#[repr(C)] +// Note: Duplicated in wgpu-rs as BindingResource #[derive(Debug)] -#[cfg_attr(feature = "trace", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub enum BindingResource { +pub enum BindingResource<'a> { Buffer(BufferBinding), Sampler(SamplerId), TextureView(TextureViewId), + TextureViewArray(&'a [TextureViewId]), } -#[repr(C)] +// Note: Duplicated in wgpu-rs as Binding #[derive(Debug)] -#[cfg_attr(feature = "trace", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct BindGroupEntry { +pub struct BindGroupEntry<'a> { pub binding: u32, - pub resource: BindingResource, + pub resource: BindingResource<'a>, } -#[repr(C)] +// Note: Duplicated in wgpu-rs as BindGroupDescriptor #[derive(Debug)] -pub struct BindGroupDescriptor { - pub label: *const std::os::raw::c_char, +pub struct BindGroupDescriptor<'a> { + pub label: Option<&'a str>, pub layout: BindGroupLayoutId, - pub entries: *const BindGroupEntry, - pub entries_length: usize, + pub bindings: &'a [BindGroupEntry<'a>], } #[derive(Debug)] diff --git a/gfx/wgpu/wgpu-core/src/command/mod.rs b/gfx/wgpu/wgpu-core/src/command/mod.rs index ea8ed0e5c5a7..ac6399b1de1a 100644 --- a/gfx/wgpu/wgpu-core/src/command/mod.rs +++ b/gfx/wgpu/wgpu-core/src/command/mod.rs @@ -211,6 +211,7 @@ struct PassComponent { load_op: wgt::LoadOp, store_op: wgt::StoreOp, clear_value: T, + read_only: bool, } // required for PeekPoke @@ -220,6 +221,7 @@ impl Default for PassComponent { load_op: wgt::LoadOp::Clear, store_op: wgt::StoreOp::Clear, clear_value: T::default(), + read_only: false, } } } diff --git a/gfx/wgpu/wgpu-core/src/command/render.rs b/gfx/wgpu/wgpu-core/src/command/render.rs index bab58d3e96f6..b0d77ac77589 100644 --- a/gfx/wgpu/wgpu-core/src/command/render.rs +++ b/gfx/wgpu/wgpu-core/src/command/render.rs @@ -37,6 +37,14 @@ pub type RenderPassColorAttachmentDescriptor = pub type RenderPassDepthStencilAttachmentDescriptor = RenderPassDepthStencilAttachmentDescriptorBase; +fn is_depth_stencil_read_only( + desc: &RenderPassDepthStencilAttachmentDescriptor, + aspects: hal::format::Aspects, +) -> bool { + (desc.depth_read_only || !aspects.contains(hal::format::Aspects::DEPTH)) + && (desc.stencil_read_only || !aspects.contains(hal::format::Aspects::STENCIL)) +} + #[repr(C)] #[derive(Debug)] pub struct RenderPassDescriptor<'a> { @@ -130,11 +138,13 @@ impl super::RawPass { load_op: ds.depth_load_op, store_op: ds.depth_store_op, clear_value: ds.clear_depth, + read_only: ds.depth_read_only, }, stencil: PassComponent { load_op: ds.stencil_load_op, store_op: ds.stencil_store_op, clear_value: ds.clear_stencil, + read_only: ds.stencil_read_only, }, }; } @@ -150,6 +160,7 @@ impl super::RawPass { load_op: at.load_op, store_op: at.store_op, clear_value: at.clear_color, + read_only: false, }, }; } @@ -361,13 +372,19 @@ impl Global { attachment: id::TextureViewId::from_raw(at.attachment).unwrap(), depth_load_op: at.depth.load_op, depth_store_op: at.depth.store_op, + depth_read_only: at.depth.read_only, clear_depth: at.depth.clear_value, stencil_load_op: at.stencil.load_op, stencil_store_op: at.stencil.store_op, clear_stencil: at.stencil.clear_value, + stencil_read_only: at.stencil.read_only, }; Some(&depth_stencil_attachment_body) }; + // We default to false intentionally, even if depth-stencil isn't used at all. + // This allows us to use the primary raw pipeline in `RenderPipeline`, + // instead of the special read-only one, which would be `None`. + let mut is_ds_read_only = false; let (context, sample_count) = { use hal::device::Device as _; @@ -388,11 +405,12 @@ impl Global { ); const MAX_TOTAL_ATTACHMENTS: usize = 10; - type OutputAttachment<'a> = ( - &'a Stored, - &'a hal::image::SubresourceRange, - Option, - ); + struct OutputAttachment<'a> { + texture_id: &'a Stored, + range: &'a hal::image::SubresourceRange, + previous_use: Option, + new_use: TextureUse, + } let mut output_attachments = ArrayVec::<[OutputAttachment; MAX_TOTAL_ATTACHMENTS]>::new(); @@ -420,23 +438,29 @@ impl Global { }; // Using render pass for transition. - let consistent_use = base_trackers + let previous_use = base_trackers .textures .query(source_id.value, view.range.clone()); - output_attachments.push((source_id, &view.range, consistent_use)); + let new_use = if is_depth_stencil_read_only(at, view.range.aspects) { + is_ds_read_only = true; + TextureUse::ATTACHMENT_READ + } else { + TextureUse::ATTACHMENT_WRITE + }; + output_attachments.push(OutputAttachment { + texture_id: source_id, + range: &view.range, + previous_use, + new_use, + }); - let old_layout = match consistent_use { - Some(usage) => { - conv::map_texture_state( - usage, - hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL, - ) - .1 - } - None => hal::image::Layout::DepthStencilAttachmentOptimal, + let new_layout = conv::map_texture_state(new_use, view.range.aspects).1; + let old_layout = match previous_use { + Some(usage) => conv::map_texture_state(usage, view.range.aspects).1, + None => new_layout, }; - Some(hal::pass::Attachment { + let ds_at = hal::pass::Attachment { format: Some(conv::map_texture_format( view.format, device.private_features, @@ -447,8 +471,9 @@ impl Global { at.stencil_load_op, at.stencil_store_op, ), - layouts: old_layout..hal::image::Layout::DepthStencilAttachmentOptimal, - }) + layouts: old_layout..new_layout, + }; + Some((ds_at, new_layout)) } None => None, }; @@ -473,18 +498,26 @@ impl Global { let layouts = match view.inner { TextureViewInner::Native { ref source_id, .. } => { - let consistent_use = base_trackers + let previous_use = base_trackers .textures .query(source_id.value, view.range.clone()); - output_attachments.push((source_id, &view.range, consistent_use)); + let new_use = TextureUse::ATTACHMENT_WRITE; + output_attachments.push(OutputAttachment { + texture_id: source_id, + range: &view.range, + previous_use, + new_use, + }); - let old_layout = match consistent_use { + let new_layout = + conv::map_texture_state(new_use, hal::format::Aspects::COLOR).1; + let old_layout = match previous_use { Some(usage) => { conv::map_texture_state(usage, hal::format::Aspects::COLOR).1 } - None => hal::image::Layout::ColorAttachmentOptimal, + None => new_layout, }; - old_layout..hal::image::Layout::ColorAttachmentOptimal + old_layout..new_layout } TextureViewInner::SwapChain { ref source_id, .. } => { if let Some((ref sc_id, _)) = cmb.used_swap_chain { @@ -506,7 +539,7 @@ impl Global { } }; - colors.push(hal::pass::Attachment { + let color_at = hal::pass::Attachment { format: Some(conv::map_texture_format( view.format, device.private_features, @@ -515,7 +548,8 @@ impl Global { ops: conv::map_load_store_ops(at.load_op, at.store_op), stencil_ops: hal::pass::AttachmentOps::DONT_CARE, layouts, - }); + }; + colors.push((color_at, hal::image::Layout::ColorAttachmentOptimal)); } for resolve_target in color_attachments.iter().flat_map(|at| at.resolve_target) { @@ -535,18 +569,26 @@ impl Global { let layouts = match view.inner { TextureViewInner::Native { ref source_id, .. } => { - let consistent_use = base_trackers + let previous_use = base_trackers .textures .query(source_id.value, view.range.clone()); - output_attachments.push((source_id, &view.range, consistent_use)); + let new_use = TextureUse::ATTACHMENT_WRITE; + output_attachments.push(OutputAttachment { + texture_id: source_id, + range: &view.range, + previous_use, + new_use, + }); - let old_layout = match consistent_use { + let new_layout = + conv::map_texture_state(new_use, hal::format::Aspects::COLOR).1; + let old_layout = match previous_use { Some(usage) => { conv::map_texture_state(usage, hal::format::Aspects::COLOR).1 } - None => hal::image::Layout::ColorAttachmentOptimal, + None => new_layout, }; - old_layout..hal::image::Layout::ColorAttachmentOptimal + old_layout..new_layout } TextureViewInner::SwapChain { ref source_id, .. } => { if let Some((ref sc_id, _)) = cmb.used_swap_chain { @@ -562,7 +604,7 @@ impl Global { } }; - resolves.push(hal::pass::Attachment { + let resolve_at = hal::pass::Attachment { format: Some(conv::map_texture_format( view.format, device.private_features, @@ -574,7 +616,8 @@ impl Global { ), stencil_ops: hal::pass::AttachmentOps::DONT_CARE, layouts, - }); + }; + resolves.push((resolve_at, hal::image::Layout::ColorAttachmentOptimal)); } RenderPassKey { @@ -584,30 +627,29 @@ impl Global { } }; - for (source_id, view_range, consistent_use) in output_attachments { - let texture = &texture_guard[source_id.value]; + for ot in output_attachments { + let texture = &texture_guard[ot.texture_id.value]; assert!( texture.usage.contains(TextureUsage::OUTPUT_ATTACHMENT), "Texture usage {:?} must contain the usage flag OUTPUT_ATTACHMENT", texture.usage ); - let usage = consistent_use.unwrap_or(TextureUse::OUTPUT_ATTACHMENT); // this is important to record the `first` state. let _ = trackers.textures.change_replace( - source_id.value, - &source_id.ref_count, - view_range.clone(), - usage, + ot.texture_id.value, + &ot.texture_id.ref_count, + ot.range.clone(), + ot.previous_use.unwrap_or(ot.new_use), ); - if consistent_use.is_some() { + if ot.previous_use.is_some() { // If we expect the texture to be transited to a new state by the // render pass configuration, make the tracker aware of that. let _ = trackers.textures.change_replace( - source_id.value, - &source_id.ref_count, - view_range.clone(), - TextureUse::OUTPUT_ATTACHMENT, + ot.texture_id.value, + &ot.texture_id.ref_count, + ot.range.clone(), + ot.new_use, ); }; } @@ -615,8 +657,8 @@ impl Global { let mut render_pass_cache = device.render_passes.lock(); let render_pass = match render_pass_cache.entry(rp_key.clone()) { Entry::Occupied(e) => e.into_mut(), - Entry::Vacant(e) => { - let color_ids = [ + Entry::Vacant(entry) => { + let color_ids: [hal::pass::AttachmentRef; MAX_COLOR_TARGETS] = [ (0, hal::image::Layout::ColorAttachmentOptimal), (1, hal::image::Layout::ColorAttachmentOptimal), (2, hal::image::Layout::ColorAttachmentOptimal), @@ -629,49 +671,55 @@ impl Global { .iter() .any(|at| at.resolve_target.is_some()) { - for (i, at) in color_attachments.iter().enumerate() { - if at.resolve_target.is_none() { - resolve_ids.push(( - hal::pass::ATTACHMENT_UNUSED, - hal::image::Layout::ColorAttachmentOptimal, - )); - } else { - let sample_count_check = - view_guard[color_attachments[i].attachment].samples; - assert!( - sample_count_check > 1, - "RenderPassColorAttachmentDescriptor with a resolve_target must have an attachment with sample_count > 1, had a sample count of {}", - sample_count_check - ); - resolve_ids.push(( - attachment_index, - hal::image::Layout::ColorAttachmentOptimal, - )); - attachment_index += 1; - } + for ((i, at), &(_, layout)) in color_attachments + .iter() + .enumerate() + .zip(entry.key().resolves.iter()) + { + let real_attachment_index = match at.resolve_target { + Some(resolve_attachment) => { + assert_ne!( + view_guard[at.attachment].samples, + 1, + "RenderPassColorAttachmentDescriptor's attachment with a resolve_target must be multi-sampled", + ); + assert_eq!( + view_guard[resolve_attachment].samples, + 1, + "RenderPassColorAttachmentDescriptor's resolve_target must not be multi-sampled", + ); + attachment_index + i + } + None => hal::pass::ATTACHMENT_UNUSED, + }; + resolve_ids.push((real_attachment_index, layout)); } + attachment_index += color_attachments.len(); } - let depth_id = ( - attachment_index, - hal::image::Layout::DepthStencilAttachmentOptimal, - ); + let depth_id = depth_stencil_attachment.map(|at| { + let aspects = view_guard[at.attachment].range.aspects; + let usage = if is_depth_stencil_read_only(at, aspects) { + TextureUse::ATTACHMENT_READ + } else { + TextureUse::ATTACHMENT_WRITE + }; + (attachment_index, conv::map_texture_state(usage, aspects).1) + }); let subpass = hal::pass::SubpassDesc { colors: &color_ids[..color_attachments.len()], resolves: &resolve_ids, - depth_stencil: depth_stencil_attachment.map(|_| &depth_id), + depth_stencil: depth_id.as_ref(), inputs: &[], preserves: &[], }; + let all = entry.key().all().map(|(at, _)| at); - let pass = unsafe { - device - .raw - .create_render_pass(e.key().all(), &[subpass], &[]) - } - .unwrap(); - e.insert(pass) + let pass = + unsafe { device.raw.create_render_pass(all, iter::once(subpass), &[]) } + .unwrap(); + entry.insert(pass) } }; @@ -744,13 +792,13 @@ impl Global { let clear_values = color_attachments .iter() .zip(&rp_key.colors) - .flat_map(|(at, key)| { + .flat_map(|(at, (rat, _layout))| { match at.load_op { LoadOp::Load => None, LoadOp::Clear => { use hal::format::ChannelType; //TODO: validate sign/unsign and normalized ranges of the color values - let value = match key.format.unwrap().base_format().1 { + let value = match rat.format.unwrap().base_format().1 { ChannelType::Unorm | ChannelType::Snorm | ChannelType::Ufloat @@ -919,12 +967,17 @@ impl Global { assert!( context.compatible(&pipeline.pass_context), - "The render pipeline is not compatible with the pass!" + "The render pipeline output formats do not match render pass attachment formats!" ); assert_eq!( pipeline.sample_count, sample_count, "The render pipeline and renderpass have mismatching sample_count" ); + assert!( + !is_ds_read_only || pipeline.flags.contains(PipelineFlags::DEPTH_STENCIL_READ_ONLY), + "Pipeline {:?} is not compatible with the depth-stencil read-only render pass", + pipeline_id + ); state .blend_color diff --git a/gfx/wgpu/wgpu-core/src/command/transfer.rs b/gfx/wgpu/wgpu-core/src/command/transfer.rs index 2d4e5d32098b..bfb1ab98e894 100644 --- a/gfx/wgpu/wgpu-core/src/command/transfer.rs +++ b/gfx/wgpu/wgpu-core/src/command/transfer.rs @@ -15,6 +15,7 @@ use crate::{ use hal::command::CommandBuffer as _; use wgt::{BufferAddress, BufferUsage, Extent3d, Origin3d, TextureDataLayout, TextureUsage}; +use std::convert::TryInto as _; use std::iter; pub(crate) const BITS_PER_BYTE: u32 = 8; @@ -82,6 +83,179 @@ impl TextureCopyView { } } +/// Function copied with minor modifications from webgpu standard https://gpuweb.github.io/gpuweb/#valid-texture-copy-range +pub(crate) fn validate_linear_texture_data( + layout: &TextureDataLayout, + buffer_size: BufferAddress, + bytes_per_texel: BufferAddress, + copy_size: &Extent3d, +) { + // Convert all inputs to BufferAddress (u64) to prevent overflow issues + let copy_width = copy_size.width as BufferAddress; + let copy_height = copy_size.height as BufferAddress; + let copy_depth = copy_size.depth as BufferAddress; + + let offset = layout.offset; + let rows_per_image = layout.rows_per_image as BufferAddress; + let bytes_per_row = layout.bytes_per_row as BufferAddress; + + // TODO: Once compressed textures are supported, these needs to be fixed + let block_width: BufferAddress = 1; + let block_height: BufferAddress = 1; + let block_size = bytes_per_texel; + + assert_eq!( + copy_width % block_width, + 0, + "Copy width {} must be a multiple of texture block width {}", + copy_size.width, + block_width, + ); + assert_eq!( + copy_height % block_height, + 0, + "Copy height {} must be a multiple of texture block height {}", + copy_size.height, + block_height, + ); + assert_eq!( + rows_per_image % block_height, + 0, + "Rows per image {} must be a multiple of image format block height {}", + rows_per_image, + block_height, + ); + + let bytes_in_a_complete_row = block_size * copy_width / block_width; + let required_bytes_in_copy = if copy_width == 0 || copy_height == 0 || copy_depth == 0 { + 0 + } else { + let actual_rows_per_image = if rows_per_image == 0 { + copy_height + } else { + rows_per_image + }; + let texel_block_rows_per_image = actual_rows_per_image / block_height; + let bytes_per_image = bytes_per_row * texel_block_rows_per_image; + let bytes_in_last_slice = + bytes_per_row * (copy_height / block_height - 1) + bytes_in_a_complete_row; + bytes_per_image * (copy_depth - 1) + bytes_in_last_slice + }; + + if rows_per_image != 0 { + assert!( + rows_per_image >= copy_height, + "Rows per image {} must be greater or equal to copy_extent.height {}", + rows_per_image, + copy_height + ) + } + assert!( + offset + required_bytes_in_copy <= buffer_size, + "Texture copy using buffer indices {}..{} would overrun buffer of size {}", + offset, + offset + required_bytes_in_copy, + buffer_size + ); + assert_eq!( + offset % block_size, + 0, + "Buffer offset {} must be a multiple of image format block size {}", + offset, + block_size, + ); + if copy_height > 1 { + assert!( + bytes_per_row >= bytes_in_a_complete_row, + "Bytes per row {} must be at least the size of {} {}-byte texel blocks ({})", + bytes_per_row, + copy_width / block_width, + block_size, + bytes_in_a_complete_row, + ) + } + if copy_depth > 1 { + assert_ne!( + rows_per_image, 0, + "Rows per image {} must be set to a non zero value when copy depth > 1 ({})", + rows_per_image, copy_depth, + ) + } +} + +/// Function copied with minor modifications from webgpu standard https://gpuweb.github.io/gpuweb/#valid-texture-copy-range +pub(crate) fn validate_texture_copy_range( + texture_copy_view: &TextureCopyView, + texture_dimension: hal::image::Kind, + copy_size: &Extent3d, +) { + // TODO: Once compressed textures are supported, these needs to be fixed + let block_width: u32 = 1; + let block_height: u32 = 1; + + let mut extent = texture_dimension.level_extent( + texture_copy_view + .mip_level + .try_into() + .expect("Mip level must be < 256"), + ); + match texture_dimension { + hal::image::Kind::D1(..) => { + assert_eq!( + (copy_size.height, copy_size.depth), + (1, 1), + "Copies with 1D textures must have height and depth of 1. Currently: ({}, {})", + copy_size.height, + copy_size.depth, + ); + } + hal::image::Kind::D2(_, _, array_layers, _) => { + extent.depth = array_layers as u32; + } + hal::image::Kind::D3(..) => {} + }; + + let x_copy_max = texture_copy_view.origin.x + copy_size.width; + assert!( + x_copy_max <= extent.width, + "Texture copy with X range {}..{} overruns texture width {}", + texture_copy_view.origin.x, + x_copy_max, + extent.width, + ); + let y_copy_max = texture_copy_view.origin.y + copy_size.height; + assert!( + y_copy_max <= extent.height, + "Texture copy with Y range {}..{} overruns texture height {}", + texture_copy_view.origin.y, + y_copy_max, + extent.height, + ); + let z_copy_max = texture_copy_view.origin.z + copy_size.depth; + assert!( + z_copy_max <= extent.depth, + "Texture copy with Z range {}..{} overruns texture depth {}", + texture_copy_view.origin.z, + z_copy_max, + extent.depth, + ); + + assert_eq!( + copy_size.width % block_width, + 0, + "Copy width {} must be a multiple of texture block width {}", + copy_size.width, + block_width, + ); + assert_eq!( + copy_size.height % block_height, + 0, + "Copy height {} must be a multiple of texture block height {}", + copy_size.height, + block_height, + ); +} + impl Global { pub fn command_encoder_copy_buffer_to_buffer( &self, @@ -114,6 +288,11 @@ impl Global { None => (), } + if size == 0 { + log::trace!("Ignoring copy_buffer_to_buffer of size 0"); + return; + } + let (src_buffer, src_pending) = cmb.trackers .buffers @@ -136,6 +315,47 @@ impl Global { ); barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_buffer))); + assert_eq!( + size % wgt::COPY_BUFFER_ALIGNMENT, + 0, + "Buffer copy size {} must be a multiple of {}", + size, + wgt::COPY_BUFFER_ALIGNMENT, + ); + assert_eq!( + source_offset % wgt::COPY_BUFFER_ALIGNMENT, + 0, + "Buffer source offset {} must be a multiple of {}", + source_offset, + wgt::COPY_BUFFER_ALIGNMENT, + ); + assert_eq!( + destination_offset % wgt::COPY_BUFFER_ALIGNMENT, + 0, + "Buffer destination offset {} must be a multiple of {}", + destination_offset, + wgt::COPY_BUFFER_ALIGNMENT, + ); + + let source_start_offset = source_offset; + let source_end_offset = source_offset + size; + let destination_start_offset = destination_offset; + let destination_end_offset = destination_offset + size; + assert!( + source_end_offset <= src_buffer.size, + "Buffer to buffer copy with indices {}..{} overruns source buffer of size {}", + source_start_offset, + source_end_offset, + src_buffer.size + ); + assert!( + destination_end_offset <= dst_buffer.size, + "Buffer to buffer copy with indices {}..{} overruns destination buffer of size {}", + destination_start_offset, + destination_end_offset, + dst_buffer.size + ); + let region = hal::command::BufferCopy { src: source_offset, dst: destination_offset, @@ -177,6 +397,11 @@ impl Global { None => (), } + if copy_size.width == 0 || copy_size.height == 0 || copy_size.width == 0 { + log::trace!("Ignoring copy_buffer_to_texture of size 0"); + return; + } + let (src_buffer, src_pending) = cmb.trackers.buffers.use_replace( &*buffer_guard, source.buffer, @@ -207,6 +432,14 @@ impl Global { source.layout.bytes_per_row, wgt::COPY_BYTES_PER_ROW_ALIGNMENT ); + validate_texture_copy_range(destination, dst_texture.kind, copy_size); + validate_linear_texture_data( + &source.layout, + src_buffer.size, + bytes_per_texel as BufferAddress, + copy_size, + ); + let buffer_width = source.layout.bytes_per_row / bytes_per_texel; let region = hal::command::BufferImageCopy { buffer_offset: source.layout.offset, @@ -257,6 +490,11 @@ impl Global { None => (), } + if copy_size.width == 0 || copy_size.height == 0 || copy_size.width == 0 { + log::trace!("Ignoring copy_texture_to_buffer of size 0"); + return; + } + let (src_texture, src_pending) = cmb.trackers.textures.use_replace( &*texture_guard, source.texture, @@ -295,6 +533,14 @@ impl Global { destination.layout.bytes_per_row, wgt::COPY_BYTES_PER_ROW_ALIGNMENT ); + validate_texture_copy_range(source, src_texture.kind, copy_size); + validate_linear_texture_data( + &destination.layout, + dst_buffer.size, + bytes_per_texel as BufferAddress, + copy_size, + ); + let buffer_width = destination.layout.bytes_per_row / bytes_per_texel; let region = hal::command::BufferImageCopy { buffer_offset: destination.layout.offset, @@ -351,6 +597,11 @@ impl Global { None => (), } + if copy_size.width == 0 || copy_size.height == 0 || copy_size.width == 0 { + log::trace!("Ignoring copy_texture_to_texture of size 0"); + return; + } + let (src_texture, src_pending) = cmb.trackers.textures.use_replace( &*texture_guard, source.texture, @@ -378,6 +629,9 @@ impl Global { barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_texture))); assert_eq!(src_texture.dimension, dst_texture.dimension); + validate_texture_copy_range(source, src_texture.kind, copy_size); + validate_texture_copy_range(destination, dst_texture.kind, copy_size); + let region = hal::command::ImageCopy { src_subresource: src_layers, src_offset, diff --git a/gfx/wgpu/wgpu-core/src/conv.rs b/gfx/wgpu/wgpu-core/src/conv.rs index 0cf4cd1ffaa9..dec551f12d9a 100644 --- a/gfx/wgpu/wgpu-core/src/conv.rs +++ b/gfx/wgpu/wgpu-core/src/conv.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crate::{binding_model, resource, PrivateFeatures}; +use crate::{resource, PrivateFeatures}; pub fn map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties) { use hal::buffer::Usage as U; @@ -75,40 +75,36 @@ pub fn map_texture_usage( value } -pub fn map_binding_type(binding: &binding_model::BindGroupLayoutEntry) -> hal::pso::DescriptorType { - use crate::binding_model::BindingType as Bt; +pub fn map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType { use hal::pso; + use wgt::BindingType as Bt; match binding.ty { - Bt::UniformBuffer => pso::DescriptorType::Buffer { + Bt::UniformBuffer { dynamic } => pso::DescriptorType::Buffer { ty: pso::BufferDescriptorType::Uniform, format: pso::BufferDescriptorFormat::Structured { - dynamic_offset: binding.has_dynamic_offset, + dynamic_offset: dynamic, }, }, - Bt::StorageBuffer => pso::DescriptorType::Buffer { - ty: pso::BufferDescriptorType::Storage { read_only: false }, + Bt::StorageBuffer { readonly, dynamic } => pso::DescriptorType::Buffer { + ty: pso::BufferDescriptorType::Storage { + read_only: readonly, + }, format: pso::BufferDescriptorFormat::Structured { - dynamic_offset: binding.has_dynamic_offset, + dynamic_offset: dynamic, }, }, - Bt::ReadonlyStorageBuffer => pso::DescriptorType::Buffer { - ty: pso::BufferDescriptorType::Storage { read_only: true }, - format: pso::BufferDescriptorFormat::Structured { - dynamic_offset: binding.has_dynamic_offset, - }, - }, - Bt::Sampler | Bt::ComparisonSampler => pso::DescriptorType::Sampler, - Bt::SampledTexture => pso::DescriptorType::Image { + Bt::Sampler { .. } => pso::DescriptorType::Sampler, + Bt::SampledTexture { .. } => pso::DescriptorType::Image { ty: pso::ImageDescriptorType::Sampled { with_sampler: false, }, }, - Bt::ReadonlyStorageTexture => pso::DescriptorType::Image { - ty: pso::ImageDescriptorType::Storage { read_only: true }, - }, - Bt::WriteonlyStorageTexture => pso::DescriptorType::Image { - ty: pso::ImageDescriptorType::Storage { read_only: false }, + Bt::StorageTexture { readonly, .. } => pso::DescriptorType::Image { + ty: pso::ImageDescriptorType::Storage { + read_only: readonly, + }, }, + _ => unreachable!(), } } @@ -371,14 +367,14 @@ pub(crate) fn map_texture_format( // Depth and stencil formats Tf::Depth32Float => H::D32Sfloat, Tf::Depth24Plus => { - if private_features.supports_texture_d24_s8 { + if private_features.texture_d24_s8 { H::D24UnormS8Uint } else { H::D32Sfloat } } Tf::Depth24PlusStencil8 => { - if private_features.supports_texture_d24_s8 { + if private_features.texture_d24_s8 { H::D24UnormS8Uint } else { H::D32SfloatS8Uint @@ -530,8 +526,9 @@ pub(crate) fn map_texture_state( W::COPY_SRC => L::TransferSrcOptimal, W::COPY_DST => L::TransferDstOptimal, W::SAMPLED => L::ShaderReadOnlyOptimal, - W::OUTPUT_ATTACHMENT if is_color => L::ColorAttachmentOptimal, - W::OUTPUT_ATTACHMENT => L::DepthStencilAttachmentOptimal, //TODO: read-only depth/stencil + W::ATTACHMENT_READ | W::ATTACHMENT_WRITE if is_color => L::ColorAttachmentOptimal, + W::ATTACHMENT_READ => L::DepthStencilReadOnlyOptimal, + W::ATTACHMENT_WRITE => L::DepthStencilAttachmentOptimal, _ => L::General, }; @@ -545,8 +542,14 @@ pub(crate) fn map_texture_state( if usage.contains(W::SAMPLED) { access |= A::SHADER_READ; } - if usage.contains(W::OUTPUT_ATTACHMENT) { - //TODO: read-only attachments + if usage.contains(W::ATTACHMENT_READ) { + access |= if is_color { + A::COLOR_ATTACHMENT_READ + } else { + A::DEPTH_STENCIL_ATTACHMENT_READ + }; + } + if usage.contains(W::ATTACHMENT_WRITE) { access |= if is_color { A::COLOR_ATTACHMENT_WRITE } else { diff --git a/gfx/wgpu/wgpu-core/src/device/life.rs b/gfx/wgpu/wgpu-core/src/device/life.rs index 4b92d849d272..9d69abfceb33 100644 --- a/gfx/wgpu/wgpu-core/src/device/life.rs +++ b/gfx/wgpu/wgpu-core/src/device/life.rs @@ -657,19 +657,22 @@ impl LifetimeTracker { _ => panic!("No pending mapping."), }; log::debug!("Buffer {:?} map state -> Active", buffer_id); - let host = match mapping.op { - resource::BufferMapOperation::Read { .. } => super::HostMap::Read, - resource::BufferMapOperation::Write { .. } => super::HostMap::Write, + let host = mapping.op.host; + let status = match super::map_buffer(raw, buffer, mapping.sub_range.clone(), host) { + Ok(ptr) => { + buffer.map_state = resource::BufferMapState::Active { + ptr, + sub_range: mapping.sub_range, + host, + }; + resource::BufferMapAsyncStatus::Success + } + Err(e) => { + log::error!("Mapping failed {:?}", e); + resource::BufferMapAsyncStatus::Error + } }; - let result = super::map_buffer(raw, buffer, mapping.sub_range.clone(), host); - if let Ok(ptr) = result { - buffer.map_state = resource::BufferMapState::Active { - ptr, - sub_range: mapping.sub_range, - host, - }; - } - pending_callbacks.push((mapping.op, result)); + pending_callbacks.push((mapping.op, status)); } } pending_callbacks diff --git a/gfx/wgpu/wgpu-core/src/device/mod.rs b/gfx/wgpu/wgpu-core/src/device/mod.rs index 829cee5697c1..6e0428a1b0f7 100644 --- a/gfx/wgpu/wgpu-core/src/device/mod.rs +++ b/gfx/wgpu/wgpu-core/src/device/mod.rs @@ -2,12 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// temporary: to allow `as *const _` on `std::os::raw::c_char` +#![allow(trivial_casts)] + use crate::{ binding_model, command, conv, hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token}, id, pipeline, resource, swap_chain, track::{BufferState, TextureState, TrackerSet}, - FastHashMap, LifeGuard, PrivateFeatures, Stored, + validation, FastHashMap, LifeGuard, PrivateFeatures, Stored, MAX_BIND_GROUPS, }; use arrayvec::ArrayVec; @@ -26,7 +29,7 @@ use wgt::{ }; use std::{ - collections::hash_map::Entry, ffi, iter, marker::PhantomData, ptr, slice, + collections::hash_map::Entry, ffi, iter, marker::PhantomData, mem, ptr, slice, sync::atomic::Ordering, }; @@ -37,6 +40,7 @@ mod queue; #[cfg(any(feature = "trace", feature = "replay"))] pub mod trace; +use smallvec::SmallVec; #[cfg(feature = "trace")] use trace::{Action, Trace}; @@ -78,6 +82,7 @@ pub fn all_image_stages() -> hal::pso::PipelineStage { | Ps::TRANSFER } +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum HostMap { Read, @@ -107,22 +112,12 @@ impl RenderPassContext { } } -pub(crate) type RenderPassKey = AttachmentData; +pub(crate) type RenderPassKey = AttachmentData<(hal::pass::Attachment, hal::image::Layout)>; pub(crate) type FramebufferKey = AttachmentData; pub(crate) type RenderPassContext = AttachmentData; -// This typedef is needed to work around cbindgen limitations. -type RawBufferMut = *mut u8; -type BufferMapResult = Result; -type BufferMapPendingCallback = (resource::BufferMapOperation, BufferMapResult); - -pub type BufferMapReadCallback = unsafe extern "C" fn( - status: resource::BufferMapAsyncStatus, - data: *const u8, - userdata: *mut u8, -); -pub type BufferMapWriteCallback = - unsafe extern "C" fn(status: resource::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8); +type BufferMapResult = Result, hal::device::MapError>; +type BufferMapPendingCallback = (resource::BufferMapOperation, resource::BufferMapAsyncStatus); fn map_buffer( raw: &B::Device, @@ -153,7 +148,7 @@ fn map_buffer( HostMap::Write if needs_sync => Some(segment), _ => None, }; - Ok(ptr.as_ptr()) + Ok(ptr) } fn unmap_buffer(raw: &B::Device, buffer: &mut resource::Buffer) { @@ -168,22 +163,8 @@ fn unmap_buffer(raw: &B::Device, buffer: &mut resource::Buffer< //Note: this logic is specifically moved out of `handle_mapping()` in order to // have nothing locked by the time we execute users callback code. fn fire_map_callbacks>(callbacks: I) { - for (operation, result) in callbacks { - let (status, ptr) = match result { - Ok(ptr) => (resource::BufferMapAsyncStatus::Success, ptr), - Err(e) => { - log::error!("failed to map buffer: {:?}", e); - (resource::BufferMapAsyncStatus::Error, ptr::null_mut()) - } - }; - match operation { - resource::BufferMapOperation::Read { callback, userdata } => unsafe { - callback(status, ptr, userdata) - }, - resource::BufferMapOperation::Write { callback, userdata } => unsafe { - callback(status, ptr, userdata) - }, - } + for (operation, status) in callbacks { + unsafe { (operation.callback)(status, operation.user_data) } } } @@ -206,6 +187,8 @@ pub struct Device { pub(crate) private_features: PrivateFeatures, limits: wgt::Limits, extensions: wgt::Extensions, + //TODO: move this behind another mutex. This would allow several methods to switch + // to borrow Device immutably, such as `write_buffer`, `write_texture`, and `buffer_unmap`. pending_writes: queue::PendingWrites, #[cfg(feature = "trace")] pub(crate) trace: Option>, @@ -218,7 +201,7 @@ impl Device { queue_group: hal::queue::QueueGroup, mem_props: hal::adapter::MemoryProperties, hal_limits: hal::Limits, - supports_texture_d24_s8: bool, + private_features: PrivateFeatures, desc: &wgt::DeviceDescriptor, trace_path: Option<&std::path::Path>, ) -> Self { @@ -275,9 +258,7 @@ impl Device { } }), hal_limits, - private_features: PrivateFeatures { - supports_texture_d24_s8, - }, + private_features, limits: desc.limits.clone(), extensions: desc.extensions.clone(), pending_writes: queue::PendingWrites::new(), @@ -327,32 +308,42 @@ impl Device { &self, self_id: id::DeviceId, desc: &wgt::BufferDescriptor