Skip to content

Commit 9308754

Browse files
greggmanDawn LUCI CQ
authored andcommitted
Capture and Replay initial commit
Get a capture and replay test working. Bug: 413053623 Change-Id: If5e3b5fc8fe437773e0de0e53bda73f085876ebd Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/261441 Reviewed-by: Corentin Wallez <[email protected]> Commit-Queue: Corentin Wallez <[email protected]> Auto-Submit: Gregg Tavares <[email protected]>
1 parent aaba549 commit 9308754

29 files changed

+1575
-6
lines changed

include/dawn/native/WebGPUBackend.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,22 @@
2828
#ifndef INCLUDE_DAWN_NATIVE_WEBGPUBACKEND_H_
2929
#define INCLUDE_DAWN_NATIVE_WEBGPUBACKEND_H_
3030

31+
#include <ostream>
32+
3133
#include "dawn/native/DawnNative.h"
3234

33-
namespace dawn::native::webgpu {} // namespace dawn::native::webgpu
35+
namespace dawn::native::webgpu {
36+
37+
using CaptureStream = std::ostream;
38+
39+
// Starts a capture on the given device.
40+
DAWN_NATIVE_EXPORT void StartCapture(WGPUDevice device,
41+
CaptureStream& commandStream,
42+
CaptureStream& contentStream);
43+
44+
// Ends a capture on the given device.
45+
DAWN_NATIVE_EXPORT void EndCapture(WGPUDevice device);
46+
47+
} // namespace dawn::native::webgpu
3448

3549
#endif // INCLUDE_DAWN_NATIVE_WEBGPUBACKEND_H_

src/dawn/BUILD.gn

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,10 @@ dawn_json_generator("webgpu_headers_gen") {
8080
group("proxy_for_jni") {
8181
deps = [ "${dawn_root}/tools/android" ]
8282
}
83+
84+
###############################################################################
85+
# Dawn capture and replay serialization
86+
###############################################################################
87+
source_set("serialization") {
88+
sources = [ "serialization/Schema.h" ]
89+
}

src/dawn/native/BUILD.gn

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,8 @@ source_set("sources") {
725725
"webgpu/BindGroupWGPU.h",
726726
"webgpu/BufferWGPU.cpp",
727727
"webgpu/BufferWGPU.h",
728+
"webgpu/CaptureContext.cpp",
729+
"webgpu/CaptureContext.h",
728730
"webgpu/CommandBufferWGPU.cpp",
729731
"webgpu/CommandBufferWGPU.h",
730732
"webgpu/ComputePipelineWGPU.cpp",
@@ -739,10 +741,13 @@ source_set("sources") {
739741
"webgpu/PipelineLayoutWGPU.h",
740742
"webgpu/QueueWGPU.cpp",
741743
"webgpu/QueueWGPU.h",
744+
"webgpu/RecordableObject.h",
742745
"webgpu/RenderPipelineWGPU.cpp",
743746
"webgpu/RenderPipelineWGPU.h",
744747
"webgpu/SamplerWGPU.cpp",
745748
"webgpu/SamplerWGPU.h",
749+
"webgpu/Serialization.cpp",
750+
"webgpu/Serialization.h",
746751
"webgpu/ShaderModuleWGPU.cpp",
747752
"webgpu/ShaderModuleWGPU.h",
748753
"webgpu/TextureWGPU.cpp",
@@ -751,6 +756,7 @@ source_set("sources") {
751756
"webgpu/ToWGPU.h",
752757
"webgpu/WebGPUError.h",
753758
]
759+
deps += [ "${dawn_root}/src/dawn:serialization" ]
754760
}
755761

756762
if ((dawn_enable_opengl || dawn_enable_vulkan) &&

src/dawn/native/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,12 +585,14 @@ endif()
585585
if (DAWN_ENABLE_WEBGPU_ON_WEBGPU)
586586
list(APPEND headers
587587
"${DAWN_INCLUDE_DIR}/dawn/native/WebGPUBackend.h"
588+
"${DAWN_INCLUDE_DIR}/dawn/serialization/Schema.h"
588589
)
589590
list(APPEND private_headers
590591
"webgpu/BackendWGPU.h"
591592
"webgpu/BindGroupWGPU.h"
592593
"webgpu/BindGroupLayoutWGPU.h"
593594
"webgpu/BufferWGPU.h"
595+
"webgpu/CaptureContext.h",
594596
"webgpu/CommandBufferWGPU.h"
595597
"webgpu/ComputePipelineWGPU.h"
596598
"webgpu/DeviceWGPU.h"
@@ -599,8 +601,10 @@ if (DAWN_ENABLE_WEBGPU_ON_WEBGPU)
599601
"webgpu/PhysicalDeviceWGPU.h"
600602
"webgpu/PipelineLayoutWGPU.h"
601603
"webgpu/QueueWGPU.h"
604+
"webgpu/RecordableObject.h",
602605
"webgpu/RenderPipelineWGPU.h"
603606
"webgpu/SamplerWGPU.h"
607+
"webgpu/Serialization.h"
604608
"webgpu/ShaderModuleWGPU.h"
605609
"webgpu/ToWGPU.h"
606610
"webgpu/TextureWGPU.h"
@@ -611,6 +615,7 @@ if (DAWN_ENABLE_WEBGPU_ON_WEBGPU)
611615
"webgpu/BindGroupWGPU.cpp"
612616
"webgpu/BindGroupLayoutWGPU.cpp"
613617
"webgpu/BufferWGPU.cpp"
618+
"webgpu/CaptureContext.cpp",
614619
"webgpu/CommandBufferWGPU.cpp"
615620
"webgpu/ComputePipelineWGPU.cpp"
616621
"webgpu/DeviceWGPU.cpp"
@@ -619,6 +624,7 @@ if (DAWN_ENABLE_WEBGPU_ON_WEBGPU)
619624
"webgpu/QueueWGPU.cpp"
620625
"webgpu/RenderPipelineWGPU.cpp"
621626
"webgpu/SamplerWGPU.cpp"
627+
"webgpu/Serialization.cpp",
622628
"webgpu/ShaderModuleWGPU.cpp"
623629
"webgpu/ToWGPU.cpp"
624630
"webgpu/TextureWGPU.cpp"

src/dawn/native/webgpu/BufferWGPU.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,19 @@
3434
#include "dawn/native/Buffer.h"
3535
#include "dawn/native/webgpu/DeviceWGPU.h"
3636
#include "dawn/native/webgpu/QueueWGPU.h"
37+
#include "dawn/native/webgpu/Serialization.h"
3738

3839
namespace dawn::native::webgpu {
3940

4041
// static
4142
ResultOrError<Ref<Buffer>> Buffer::Create(Device* device,
4243
const UnpackedPtr<BufferDescriptor>& descriptor) {
43-
auto desc = ToAPI(*descriptor);
44-
WGPUBuffer innerBuffer = device->wgpu.deviceCreateBuffer(device->GetInnerHandle(), desc);
44+
WGPUBufferDescriptor desc = *ToAPI(*descriptor);
45+
// Make the inner buffer copyable for readback if possible.
46+
if (!(desc.usage & WGPUBufferUsage_MapRead)) {
47+
desc.usage |= WGPUBufferUsage_CopySrc;
48+
}
49+
WGPUBuffer innerBuffer = device->wgpu.deviceCreateBuffer(device->GetInnerHandle(), &desc);
4550
if (innerBuffer == nullptr) {
4651
// innerBuffer can be nullptr when mappedAtCreation == true and fails.
4752
// Return an error buffer.
@@ -56,7 +61,9 @@ ResultOrError<Ref<Buffer>> Buffer::Create(Device* device,
5661
Buffer::Buffer(Device* device,
5762
const UnpackedPtr<BufferDescriptor>& descriptor,
5863
WGPUBuffer innerBuffer)
59-
: BufferBase(device, descriptor), ObjectWGPU(device->wgpu.bufferRelease) {
64+
: BufferBase(device, descriptor),
65+
RecordableObject(schema::ObjectType::Buffer),
66+
ObjectWGPU(device->wgpu.bufferRelease) {
6067
mInnerHandle = innerBuffer;
6168
mAllocatedSize = GetSize();
6269
}
@@ -136,4 +143,16 @@ void Buffer::DestroyImpl() {
136143
wgpu.bufferDestroy(mInnerHandle);
137144
}
138145

146+
void Buffer::AddReferenced(CaptureContext& captureContext) const {
147+
// Buffers do not reference other objects.
148+
}
149+
150+
void Buffer::CaptureCreationParameters(CaptureContext& captureContext) const {
151+
schema::Buffer buf{{
152+
.size = GetSize(),
153+
.usage = GetUsage(),
154+
}};
155+
Serialize(captureContext, buf);
156+
}
157+
139158
} // namespace dawn::native::webgpu

src/dawn/native/webgpu/BufferWGPU.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,21 @@
3232

3333
#include "dawn/native/webgpu/Forward.h"
3434
#include "dawn/native/webgpu/ObjectWGPU.h"
35+
#include "dawn/native/webgpu/RecordableObject.h"
3536

3637
namespace dawn::native::webgpu {
3738

3839
class Device;
3940

40-
class Buffer final : public BufferBase, public ObjectWGPU<WGPUBuffer> {
41+
class Buffer final : public BufferBase, public RecordableObject, public ObjectWGPU<WGPUBuffer> {
4142
public:
4243
static ResultOrError<Ref<Buffer>> Create(Device* device,
4344
const UnpackedPtr<BufferDescriptor>& descriptor);
4445
Buffer(Device* device, const UnpackedPtr<BufferDescriptor>& descriptor, WGPUBuffer innerBuffer);
4546

47+
void AddReferenced(CaptureContext& captureContext) const override;
48+
void CaptureCreationParameters(CaptureContext& context) const override;
49+
4650
private:
4751
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
4852
void UnmapImpl() override;
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2025 The Dawn & Tint Authors
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are met:
5+
//
6+
// 1. Redistributions of source code must retain the above copyright notice, this
7+
// list of conditions and the following disclaimer.
8+
//
9+
// 2. Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
//
13+
// 3. Neither the name of the copyright holder nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27+
28+
#include "src/dawn/native/webgpu/CaptureContext.h"
29+
30+
#include <concepts>
31+
#include <vector>
32+
33+
#include "dawn/common/StringViewUtils.h"
34+
#include "dawn/native/CommandBuffer.h"
35+
#include "dawn/native/Commands.h"
36+
#include "dawn/native/Device.h"
37+
#include "dawn/native/ObjectBase.h"
38+
#include "dawn/native/webgpu/BufferWGPU.h"
39+
#include "dawn/native/webgpu/Forward.h"
40+
#include "dawn/native/webgpu/QueueWGPU.h"
41+
#include "dawn/native/webgpu/Serialization.h"
42+
43+
namespace dawn::native::webgpu {
44+
45+
constexpr uint64_t kCopyBufferSize = 1024 * 1024;
46+
47+
void AddReferenced(CaptureContext& captureContext, const BufferBase* buffer) {}
48+
49+
void CaptureContext::CaptureCreation(schema::ObjectId id,
50+
const std::string& label,
51+
const RecordableObject* object) {
52+
schema::CreateResourceCmd cmd{{
53+
.data = {{
54+
.resource = {{
55+
.type = object->GetObjectType(),
56+
.id = id,
57+
.label = label,
58+
}},
59+
}},
60+
}};
61+
Serialize(*this, cmd);
62+
object->CaptureCreationParameters(*this);
63+
}
64+
65+
CaptureContext::CaptureContext(Device* device,
66+
std::ostream& commandStream,
67+
std::ostream& contentStream)
68+
: mDevice(device), mCommandStream(commandStream), mContentStream(contentStream) {}
69+
70+
CaptureContext::~CaptureContext() {
71+
if (mCopyBuffer) {
72+
mDevice->wgpu.bufferDestroy(mCopyBuffer);
73+
}
74+
}
75+
76+
WGPUBuffer CaptureContext::GetCopyBuffer() {
77+
if (!mCopyBuffer) {
78+
WGPUBufferDescriptor desc = {};
79+
desc.size = kCopyBufferSize;
80+
desc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_MapRead;
81+
mCopyBuffer = mDevice->wgpu.deviceCreateBuffer(mDevice->GetInnerHandle(), &desc);
82+
}
83+
return mCopyBuffer;
84+
}
85+
86+
void CaptureContext::WriteContentBytes(const void* data, size_t size) {
87+
mContentStream.write(reinterpret_cast<const char*>(data), size);
88+
}
89+
90+
void CaptureContext::WriteCommandBytes(const void* data, size_t size) {
91+
mCommandStream.write(reinterpret_cast<const char*>(data), size);
92+
mCommandBytesWritten += size;
93+
}
94+
95+
void CaptureContext::CaptureQueueWriteBuffer(BufferBase* buffer,
96+
uint64_t bufferOffset,
97+
const void* data,
98+
size_t size) {
99+
AddResource(buffer);
100+
schema::WriteBufferCmd cmd{{
101+
.data = {{
102+
.bufferId = GetId(buffer),
103+
.bufferOffset = bufferOffset,
104+
.size = size,
105+
}},
106+
}};
107+
108+
Serialize(*this, cmd);
109+
WriteContentBytes(data, size);
110+
}
111+
112+
} // namespace dawn::native::webgpu

0 commit comments

Comments
 (0)