[WebGPU backend] Add BindGroup / BindGroupLayout
Bug: 413053623
Change-Id: Iebcb23bc75089bda5307f558ec00c8f02975a20c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259858
Reviewed-by: Gregg Tavares <gman@chromium.org>
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn
index 8629509..30c2773 100644
--- a/src/dawn/native/BUILD.gn
+++ b/src/dawn/native/BUILD.gn
@@ -719,6 +719,10 @@
sources += [
"webgpu/BackendWGPU.cpp",
"webgpu/BackendWGPU.h",
+ "webgpu/BindGroupLayoutWGPU.cpp",
+ "webgpu/BindGroupLayoutWGPU.h",
+ "webgpu/BindGroupWGPU.cpp",
+ "webgpu/BindGroupWGPU.h",
"webgpu/BufferWGPU.cpp",
"webgpu/BufferWGPU.h",
"webgpu/CommandBufferWGPU.cpp",
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 354577a..4ff9ce8 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -585,6 +585,8 @@
)
list(APPEND private_headers
"webgpu/BackendWGPU.h"
+ "webgpu/BindGroupWGPU.h"
+ "webgpu/BindGroupLayoutWGPU.h"
"webgpu/BufferWGPU.h"
"webgpu/CommandBufferWGPU.h"
"webgpu/DeviceWGPU.h"
@@ -597,6 +599,8 @@
)
list(APPEND sources
"webgpu/BackendWGPU.cpp"
+ "webgpu/BindGroupWGPU.cpp"
+ "webgpu/BindGroupLayoutWGPU.cpp"
"webgpu/BufferWGPU.cpp"
"webgpu/CommandBufferWGPU.cpp"
"webgpu/DeviceWGPU.cpp"
diff --git a/src/dawn/native/webgpu/BindGroupLayoutWGPU.cpp b/src/dawn/native/webgpu/BindGroupLayoutWGPU.cpp
new file mode 100644
index 0000000..1507d31
--- /dev/null
+++ b/src/dawn/native/webgpu/BindGroupLayoutWGPU.cpp
@@ -0,0 +1,66 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "dawn/native/webgpu/BindGroupLayoutWGPU.h"
+
+#include "dawn/native/webgpu/DeviceWGPU.h"
+#include "dawn/native/webgpu/Forward.h"
+
+namespace dawn::native::webgpu {
+
+// static
+ResultOrError<Ref<BindGroupLayout>> BindGroupLayout::Create(
+ Device* device,
+ const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor) {
+ return AcquireRef(new BindGroupLayout(device, descriptor));
+}
+
+BindGroupLayout::BindGroupLayout(Device* device,
+ const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor)
+ : BindGroupLayoutInternalBase(device, descriptor),
+ ObjectWGPU(device->wgpu.bindGroupLayoutRelease),
+ mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
+ auto desc = ToAPI(*descriptor);
+ mInnerHandle = device->wgpu.deviceCreateBindGroupLayout(device->GetInnerHandle(), desc);
+ DAWN_ASSERT(mInnerHandle);
+}
+
+Ref<BindGroup> BindGroupLayout::AllocateBindGroup(
+ const UnpackedPtr<BindGroupDescriptor>& descriptor) {
+ Device* device = ToBackend(GetDevice());
+ return AcquireRef(mBindGroupAllocator->Allocate(device, descriptor));
+}
+
+void BindGroupLayout::DeallocateBindGroup(BindGroup* bindGroup) {
+ mBindGroupAllocator->Deallocate(bindGroup);
+}
+
+void BindGroupLayout::ReduceMemoryUsage() {
+ mBindGroupAllocator->DeleteEmptySlabs();
+}
+
+} // namespace dawn::native::webgpu
diff --git a/src/dawn/native/webgpu/BindGroupLayoutWGPU.h b/src/dawn/native/webgpu/BindGroupLayoutWGPU.h
new file mode 100644
index 0000000..6255f62
--- /dev/null
+++ b/src/dawn/native/webgpu/BindGroupLayoutWGPU.h
@@ -0,0 +1,59 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_NATIVE_WEBGPU_BINDGROUPLAYOUTWGPU_H_
+#define SRC_DAWN_NATIVE_WEBGPU_BINDGROUPLAYOUTWGPU_H_
+
+#include "dawn/common/MutexProtected.h"
+#include "dawn/common/SlabAllocator.h"
+#include "dawn/native/BindGroupLayoutInternal.h"
+#include "dawn/native/webgpu/BindGroupWGPU.h"
+#include "dawn/native/webgpu/ObjectWGPU.h"
+
+namespace dawn::native::webgpu {
+
+class BindGroupLayout final : public BindGroupLayoutInternalBase,
+ public ObjectWGPU<WGPUBindGroupLayout> {
+ public:
+ static ResultOrError<Ref<BindGroupLayout>> Create(
+ Device* device,
+ const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor);
+
+ Ref<BindGroup> AllocateBindGroup(const UnpackedPtr<BindGroupDescriptor>& descriptor);
+ void DeallocateBindGroup(BindGroup* bindGroup);
+ void ReduceMemoryUsage() override;
+
+ private:
+ BindGroupLayout(Device* device, const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor);
+ ~BindGroupLayout() override = default;
+
+ MutexProtected<SlabAllocator<BindGroup>> mBindGroupAllocator;
+};
+
+} // namespace dawn::native::webgpu
+
+#endif // SRC_DAWN_NATIVE_WEBGPU_BINDGROUPLAYOUTWGPU_H_
diff --git a/src/dawn/native/webgpu/BindGroupWGPU.cpp b/src/dawn/native/webgpu/BindGroupWGPU.cpp
new file mode 100644
index 0000000..c7e6be7
--- /dev/null
+++ b/src/dawn/native/webgpu/BindGroupWGPU.cpp
@@ -0,0 +1,108 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "dawn/native/webgpu/BindGroupWGPU.h"
+
+#include "absl/container/inlined_vector.h"
+#include "dawn/common/StringViewUtils.h"
+#include "dawn/native/webgpu/BindGroupLayoutWGPU.h"
+#include "dawn/native/webgpu/BufferWGPU.h"
+#include "dawn/native/webgpu/DeviceWGPU.h"
+
+namespace dawn::native::webgpu {
+
+namespace {
+
+WGPUBindGroupEntry ToWGPU(const BindGroupEntry* entry) {
+ return {
+ .nextInChain = nullptr,
+ .binding = entry->binding,
+ .buffer = entry->buffer == nullptr ? nullptr : ToBackend(entry->buffer)->GetInnerHandle(),
+ .offset = entry->offset,
+ .size = entry->size,
+ // TODO(crbug.com/413053623): replace with the following when the object implementation is
+ // done.
+ .sampler = nullptr,
+ .textureView = nullptr,
+ };
+}
+
+class ComboBindGroupDescriptor {
+ public:
+ explicit ComboBindGroupDescriptor(const BindGroupDescriptor* desc) {
+ mDesc.nextInChain = nullptr;
+ mDesc.label = ToOutputStringView(desc->label);
+ mDesc.layout = ToBackend(desc->layout->GetInternalBindGroupLayout())->GetInnerHandle();
+ mDesc.entryCount = desc->entryCount;
+ for (uint32_t i = 0; i < desc->entryCount; ++i) {
+ mEntries.push_back(ToWGPU(&desc->entries[i]));
+ }
+ mDesc.entries = mEntries.data();
+ }
+
+ const WGPUBindGroupDescriptor* Get() const { return &mDesc; }
+
+ private:
+ WGPUBindGroupDescriptor mDesc;
+ absl::InlinedVector<WGPUBindGroupEntry, 8> mEntries;
+};
+
+} // namespace
+
+// static
+ResultOrError<Ref<BindGroup>> BindGroup::Create(
+ Device* device,
+ const UnpackedPtr<BindGroupDescriptor>& descriptor) {
+ Ref<BindGroup> bindGroup =
+ ToBackend(descriptor->layout->GetInternalBindGroupLayout())->AllocateBindGroup(descriptor);
+ DAWN_TRY(bindGroup->Initialize(descriptor));
+ return bindGroup;
+}
+
+BindGroup::BindGroup(Device* device, const UnpackedPtr<BindGroupDescriptor>& descriptor)
+ : BindGroupBase(this, device, descriptor), ObjectWGPU(device->wgpu.bindGroupRelease) {
+ ComboBindGroupDescriptor desc(*descriptor);
+ mInnerHandle =
+ ToBackend(GetDevice())
+ ->wgpu.deviceCreateBindGroup(ToBackend(GetDevice())->GetInnerHandle(), desc.Get());
+ DAWN_ASSERT(mInnerHandle);
+}
+
+MaybeError BindGroup::InitializeImpl() {
+ return {};
+}
+
+void BindGroup::DeleteThis() {
+ // This function must first run the destructor and then deallocate memory. Take a reference to
+ // the BindGroupLayout+SlabAllocator before running the destructor so this function can access
+ // it afterwards and it's not destroyed prematurely.
+ Ref<BindGroupLayout> layout = ToBackend(GetLayout());
+ BindGroupBase::DeleteThis();
+ layout->DeallocateBindGroup(this);
+}
+
+} // namespace dawn::native::webgpu
diff --git a/src/dawn/native/webgpu/BindGroupWGPU.h b/src/dawn/native/webgpu/BindGroupWGPU.h
new file mode 100644
index 0000000..5d1bd02
--- /dev/null
+++ b/src/dawn/native/webgpu/BindGroupWGPU.h
@@ -0,0 +1,56 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_NATIVE_WEBGPU_BINDGROUPWGPU_H_
+#define SRC_DAWN_NATIVE_WEBGPU_BINDGROUPWGPU_H_
+
+#include "dawn/native/BindGroup.h"
+
+#include "dawn/common/PlacementAllocated.h"
+#include "dawn/native/webgpu/Forward.h"
+#include "dawn/native/webgpu/ObjectWGPU.h"
+
+namespace dawn::native::webgpu {
+
+class BindGroup final : public BindGroupBase,
+ public PlacementAllocated,
+ public ObjectWGPU<WGPUBindGroup> {
+ public:
+ static ResultOrError<Ref<BindGroup>> Create(Device* device,
+ const UnpackedPtr<BindGroupDescriptor>& descriptor);
+ BindGroup(Device* device, const UnpackedPtr<BindGroupDescriptor>& descriptor);
+
+ private:
+ ~BindGroup() override = default;
+
+ MaybeError InitializeImpl() override;
+ void DeleteThis() override;
+};
+
+} // namespace dawn::native::webgpu
+
+#endif // SRC_DAWN_NATIVE_WEBGPU_BINDGROUPWGPU_H_
diff --git a/src/dawn/native/webgpu/CommandBufferWGPU.cpp b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
index 2ea15da..c27f0d4 100644
--- a/src/dawn/native/webgpu/CommandBufferWGPU.cpp
+++ b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
@@ -31,6 +31,7 @@
#include "dawn/common/Assert.h"
#include "dawn/common/StringViewUtils.h"
+#include "dawn/native/webgpu/BindGroupWGPU.h"
#include "dawn/native/webgpu/BufferWGPU.h"
#include "dawn/native/webgpu/DeviceWGPU.h"
#include "dawn/native/webgpu/TextureWGPU.h"
@@ -238,12 +239,9 @@
if (cmd->dynamicOffsetCount > 0) {
dynamicOffsets = commands.NextData<uint32_t>(cmd->dynamicOffsetCount);
}
- // TODO(crbug.com/440123094): remove nullptr when GetInnerHandle is implemented for
- // BindGroupWGPU
- wgpu.computePassEncoderSetBindGroup(
- passEncoder, static_cast<uint32_t>(cmd->index),
- nullptr /*ToBackend(cmd->group)->GetInnerHandle()*/, cmd->dynamicOffsetCount,
- dynamicOffsets);
+ wgpu.computePassEncoderSetBindGroup(passEncoder, static_cast<uint32_t>(cmd->index),
+ ToBackend(cmd->group)->GetInnerHandle(),
+ cmd->dynamicOffsetCount, dynamicOffsets);
break;
}
case Command::InsertDebugMarker: {
diff --git a/src/dawn/native/webgpu/DeviceWGPU.cpp b/src/dawn/native/webgpu/DeviceWGPU.cpp
index 8cd3524..0aedd6d 100644
--- a/src/dawn/native/webgpu/DeviceWGPU.cpp
+++ b/src/dawn/native/webgpu/DeviceWGPU.cpp
@@ -51,6 +51,8 @@
#include "dawn/native/SwapChain.h"
#include "dawn/native/Texture.h"
#include "dawn/native/webgpu/BackendWGPU.h"
+#include "dawn/native/webgpu/BindGroupLayoutWGPU.h"
+#include "dawn/native/webgpu/BindGroupWGPU.h"
#include "dawn/native/webgpu/BufferWGPU.h"
#include "dawn/native/webgpu/CommandBufferWGPU.h"
#include "dawn/native/webgpu/PhysicalDeviceWGPU.h"
@@ -128,14 +130,11 @@
ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
const UnpackedPtr<BindGroupDescriptor>& descriptor) {
- return Ref<BindGroupBase>{nullptr};
+ return BindGroup::Create(this, descriptor);
}
ResultOrError<Ref<BindGroupLayoutInternalBase>> Device::CreateBindGroupLayoutImpl(
const UnpackedPtr<BindGroupLayoutDescriptor>& descriptor) {
- // TODO(crbug.com/413053623): Replace with webgpu::BindGroupLayout object.
- // This placeholder implementation is needed because device is creating empty BindGroupLayout
- // and getting content hash.
- return AcquireRef(new BindGroupLayoutInternalBase(this, descriptor));
+ return BindGroupLayout::Create(this, descriptor);
}
ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(
const UnpackedPtr<BufferDescriptor>& descriptor) {