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