1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // BufferWgpu.cpp:
7*8975f5c5SAndroid Build Coastguard Worker // Implements the class methods for BufferWgpu.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/wgpu/BufferWgpu.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/wgpu/ContextWgpu.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/wgpu/wgpu_utils.h"
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker namespace rx
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker namespace
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker // Based on a buffer binding target, compute the default wgpu usage flags. More can be added if the
25*8975f5c5SAndroid Build Coastguard Worker // buffer is used in new ways.
GetDefaultWGPUBufferUsageForBinding(gl::BufferBinding binding)26*8975f5c5SAndroid Build Coastguard Worker wgpu::BufferUsage GetDefaultWGPUBufferUsageForBinding(gl::BufferBinding binding)
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker switch (binding)
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::Array:
31*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::ElementArray:
32*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::Vertex | wgpu::BufferUsage::Index |
33*8975f5c5SAndroid Build Coastguard Worker wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
34*8975f5c5SAndroid Build Coastguard Worker
35*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::Uniform:
36*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopySrc |
37*8975f5c5SAndroid Build Coastguard Worker wgpu::BufferUsage::CopyDst;
38*8975f5c5SAndroid Build Coastguard Worker
39*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::PixelPack:
40*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::PixelUnpack:
43*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::CopyRead:
46*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::CopyWrite:
47*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::ShaderStorage:
48*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::Texture:
49*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::TransformFeedback:
50*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::DispatchIndirect:
51*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::DrawIndirect:
52*8975f5c5SAndroid Build Coastguard Worker case gl::BufferBinding::AtomicCounter:
53*8975f5c5SAndroid Build Coastguard Worker UNIMPLEMENTED();
54*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::None;
55*8975f5c5SAndroid Build Coastguard Worker
56*8975f5c5SAndroid Build Coastguard Worker default:
57*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
58*8975f5c5SAndroid Build Coastguard Worker return wgpu::BufferUsage::None;
59*8975f5c5SAndroid Build Coastguard Worker }
60*8975f5c5SAndroid Build Coastguard Worker }
61*8975f5c5SAndroid Build Coastguard Worker
62*8975f5c5SAndroid Build Coastguard Worker } // namespace
63*8975f5c5SAndroid Build Coastguard Worker
BufferWgpu(const gl::BufferState & state)64*8975f5c5SAndroid Build Coastguard Worker BufferWgpu::BufferWgpu(const gl::BufferState &state) : BufferImpl(state) {}
65*8975f5c5SAndroid Build Coastguard Worker
~BufferWgpu()66*8975f5c5SAndroid Build Coastguard Worker BufferWgpu::~BufferWgpu() {}
67*8975f5c5SAndroid Build Coastguard Worker
setData(const gl::Context * context,gl::BufferBinding target,const void * data,size_t size,gl::BufferUsage usage)68*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::setData(const gl::Context *context,
69*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target,
70*8975f5c5SAndroid Build Coastguard Worker const void *data,
71*8975f5c5SAndroid Build Coastguard Worker size_t size,
72*8975f5c5SAndroid Build Coastguard Worker gl::BufferUsage usage)
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker ContextWgpu *contextWgpu = webgpu::GetImpl(context);
75*8975f5c5SAndroid Build Coastguard Worker wgpu::Device device = webgpu::GetDevice(context);
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker bool hasData = data && size > 0;
78*8975f5c5SAndroid Build Coastguard Worker
79*8975f5c5SAndroid Build Coastguard Worker // Allocate a new buffer if the current one is invalid, the size is different, or the current
80*8975f5c5SAndroid Build Coastguard Worker // buffer cannot be mapped for writing when data needs to be uploaded.
81*8975f5c5SAndroid Build Coastguard Worker if (!mBuffer.valid() || mBuffer.requestedSize() != size ||
82*8975f5c5SAndroid Build Coastguard Worker (hasData && !mBuffer.canMapForWrite()))
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker // Allocate a new buffer
85*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBuffer.initBuffer(device, size, GetDefaultWGPUBufferUsageForBinding(target),
86*8975f5c5SAndroid Build Coastguard Worker webgpu::MapAtCreation::Yes));
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker if (hasData)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker ASSERT(mBuffer.canMapForWrite());
92*8975f5c5SAndroid Build Coastguard Worker
93*8975f5c5SAndroid Build Coastguard Worker if (!mBuffer.getMappedState().has_value())
94*8975f5c5SAndroid Build Coastguard Worker {
95*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, wgpu::MapMode::Write, 0, size));
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker
98*8975f5c5SAndroid Build Coastguard Worker uint8_t *mappedData = mBuffer.getMapWritePointer(0, size);
99*8975f5c5SAndroid Build Coastguard Worker memcpy(mappedData, data, size);
100*8975f5c5SAndroid Build Coastguard Worker }
101*8975f5c5SAndroid Build Coastguard Worker
102*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
103*8975f5c5SAndroid Build Coastguard Worker }
104*8975f5c5SAndroid Build Coastguard Worker
setSubData(const gl::Context * context,gl::BufferBinding target,const void * data,size_t size,size_t offset)105*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::setSubData(const gl::Context *context,
106*8975f5c5SAndroid Build Coastguard Worker gl::BufferBinding target,
107*8975f5c5SAndroid Build Coastguard Worker const void *data,
108*8975f5c5SAndroid Build Coastguard Worker size_t size,
109*8975f5c5SAndroid Build Coastguard Worker size_t offset)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker ContextWgpu *contextWgpu = webgpu::GetImpl(context);
112*8975f5c5SAndroid Build Coastguard Worker wgpu::Device device = webgpu::GetDevice(context);
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker ASSERT(mBuffer.valid());
115*8975f5c5SAndroid Build Coastguard Worker if (mBuffer.canMapForWrite())
116*8975f5c5SAndroid Build Coastguard Worker {
117*8975f5c5SAndroid Build Coastguard Worker if (!mBuffer.getMappedState().has_value())
118*8975f5c5SAndroid Build Coastguard Worker {
119*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBuffer.mapImmediate(contextWgpu, wgpu::MapMode::Write, offset, size));
120*8975f5c5SAndroid Build Coastguard Worker }
121*8975f5c5SAndroid Build Coastguard Worker
122*8975f5c5SAndroid Build Coastguard Worker uint8_t *mappedData = mBuffer.getMapWritePointer(offset, size);
123*8975f5c5SAndroid Build Coastguard Worker memcpy(mappedData, data, size);
124*8975f5c5SAndroid Build Coastguard Worker }
125*8975f5c5SAndroid Build Coastguard Worker else
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker // TODO: Upload into a staging buffer and copy to the destination buffer so that the copy
128*8975f5c5SAndroid Build Coastguard Worker // happens at the right point in time for command buffer recording.
129*8975f5c5SAndroid Build Coastguard Worker wgpu::Queue &queue = contextWgpu->getQueue();
130*8975f5c5SAndroid Build Coastguard Worker queue.WriteBuffer(mBuffer.getBuffer(), offset, data, size);
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
134*8975f5c5SAndroid Build Coastguard Worker }
135*8975f5c5SAndroid Build Coastguard Worker
copySubData(const gl::Context * context,BufferImpl * source,GLintptr sourceOffset,GLintptr destOffset,GLsizeiptr size)136*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::copySubData(const gl::Context *context,
137*8975f5c5SAndroid Build Coastguard Worker BufferImpl *source,
138*8975f5c5SAndroid Build Coastguard Worker GLintptr sourceOffset,
139*8975f5c5SAndroid Build Coastguard Worker GLintptr destOffset,
140*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr size)
141*8975f5c5SAndroid Build Coastguard Worker {
142*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker
map(const gl::Context * context,GLenum access,void ** mapPtr)145*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::map(const gl::Context *context, GLenum access, void **mapPtr)
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker
mapRange(const gl::Context * context,size_t offset,size_t length,GLbitfield access,void ** mapPtr)150*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::mapRange(const gl::Context *context,
151*8975f5c5SAndroid Build Coastguard Worker size_t offset,
152*8975f5c5SAndroid Build Coastguard Worker size_t length,
153*8975f5c5SAndroid Build Coastguard Worker GLbitfield access,
154*8975f5c5SAndroid Build Coastguard Worker void **mapPtr)
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker
unmap(const gl::Context * context,GLboolean * result)159*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::unmap(const gl::Context *context, GLboolean *result)
160*8975f5c5SAndroid Build Coastguard Worker {
161*8975f5c5SAndroid Build Coastguard Worker *result = GL_TRUE;
162*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
163*8975f5c5SAndroid Build Coastguard Worker }
164*8975f5c5SAndroid Build Coastguard Worker
getIndexRange(const gl::Context * context,gl::DrawElementsType type,size_t offset,size_t count,bool primitiveRestartEnabled,gl::IndexRange * outRange)165*8975f5c5SAndroid Build Coastguard Worker angle::Result BufferWgpu::getIndexRange(const gl::Context *context,
166*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType type,
167*8975f5c5SAndroid Build Coastguard Worker size_t offset,
168*8975f5c5SAndroid Build Coastguard Worker size_t count,
169*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartEnabled,
170*8975f5c5SAndroid Build Coastguard Worker gl::IndexRange *outRange)
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker ContextWgpu *contextWgpu = webgpu::GetImpl(context);
173*8975f5c5SAndroid Build Coastguard Worker wgpu::Device device = webgpu::GetDevice(context);
174*8975f5c5SAndroid Build Coastguard Worker
175*8975f5c5SAndroid Build Coastguard Worker if (mBuffer.getMappedState())
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mBuffer.unmap());
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker // Create a staging buffer just big enough for this index range
181*8975f5c5SAndroid Build Coastguard Worker const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
182*8975f5c5SAndroid Build Coastguard Worker const size_t stagingBufferSize =
183*8975f5c5SAndroid Build Coastguard Worker roundUpPow2(count * typeBytes, webgpu::kBufferCopyToBufferAlignment);
184*8975f5c5SAndroid Build Coastguard Worker
185*8975f5c5SAndroid Build Coastguard Worker webgpu::BufferHelper stagingBuffer;
186*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingBuffer.initBuffer(device, stagingBufferSize,
187*8975f5c5SAndroid Build Coastguard Worker wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
188*8975f5c5SAndroid Build Coastguard Worker webgpu::MapAtCreation::No));
189*8975f5c5SAndroid Build Coastguard Worker
190*8975f5c5SAndroid Build Coastguard Worker // Copy the source buffer to staging and flush the commands
191*8975f5c5SAndroid Build Coastguard Worker contextWgpu->ensureCommandEncoderCreated();
192*8975f5c5SAndroid Build Coastguard Worker wgpu::CommandEncoder &commandEncoder = contextWgpu->getCurrentCommandEncoder();
193*8975f5c5SAndroid Build Coastguard Worker commandEncoder.CopyBufferToBuffer(mBuffer.getBuffer(), offset, stagingBuffer.getBuffer(), 0,
194*8975f5c5SAndroid Build Coastguard Worker stagingBufferSize);
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::IndexRangeReadback));
197*8975f5c5SAndroid Build Coastguard Worker
198*8975f5c5SAndroid Build Coastguard Worker // Read back from the staging buffer and compute the index range
199*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingBuffer.mapImmediate(contextWgpu, wgpu::MapMode::Read, 0, stagingBufferSize));
200*8975f5c5SAndroid Build Coastguard Worker const uint8_t *data = stagingBuffer.getMapReadPointer(0, stagingBufferSize);
201*8975f5c5SAndroid Build Coastguard Worker *outRange = gl::ComputeIndexRange(type, data, count, primitiveRestartEnabled);
202*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(stagingBuffer.unmap());
203*8975f5c5SAndroid Build Coastguard Worker
204*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker
207*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
208