xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/wgpu/wgpu_helpers.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 
7 #ifndef LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_
8 #define LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_
9 
10 #include <dawn/webgpu_cpp.h>
11 #include <stdint.h>
12 #include <algorithm>
13 
14 #include "libANGLE/Error.h"
15 #include "libANGLE/ImageIndex.h"
16 #include "libANGLE/angletypes.h"
17 #include "libANGLE/renderer/wgpu/ContextWgpu.h"
18 #include "libANGLE/renderer/wgpu/wgpu_utils.h"
19 
20 namespace rx
21 {
22 
23 class ContextWgpu;
24 
25 namespace webgpu
26 {
27 
28 // WebGPU requires copy buffers bytesPerRow to be aligned to 256.
29 // https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gpuimagecopybuffer
30 static const GLuint kCopyBufferAlignment = 256;
31 
32 enum class UpdateSource
33 {
34     Clear,
35     Texture,
36 };
37 
38 struct ClearUpdate
39 {
40     ClearValues clearValues;
41     bool hasDepth;
42     bool hasStencil;
43 };
44 
45 struct SubresourceUpdate
46 {
SubresourceUpdateSubresourceUpdate47     SubresourceUpdate() {}
~SubresourceUpdateSubresourceUpdate48     ~SubresourceUpdate() {}
49 
SubresourceUpdateSubresourceUpdate50     SubresourceUpdate(UpdateSource targetUpdateSource,
51                       gl::LevelIndex newTargetLevel,
52                       wgpu::ImageCopyBuffer targetBuffer)
53     {
54         updateSource = targetUpdateSource;
55         textureData  = targetBuffer;
56         targetLevel  = newTargetLevel;
57     }
58 
SubresourceUpdateSubresourceUpdate59     SubresourceUpdate(UpdateSource targetUpdateSource,
60                       gl::LevelIndex newTargetLevel,
61                       ClearValues clearValues,
62                       bool hasDepth,
63                       bool hasStencil)
64     {
65         updateSource = targetUpdateSource;
66         targetLevel  = newTargetLevel;
67         clearData.clearValues = clearValues;
68         clearData.hasDepth    = hasDepth;
69         clearData.hasStencil  = hasStencil;
70     }
71 
72     UpdateSource updateSource;
73     ClearUpdate clearData;
74     wgpu::ImageCopyBuffer textureData;
75 
76     gl::LevelIndex targetLevel;
77 };
78 
79 wgpu::TextureDimension toWgpuTextureDimension(gl::TextureType glTextureType);
80 
81 class ImageHelper
82 {
83   public:
84     ImageHelper();
85     ~ImageHelper();
86 
87     angle::Result initImage(angle::FormatID intendedFormatID,
88                             angle::FormatID actualFormatID,
89                             wgpu::Device &device,
90                             gl::LevelIndex firstAllocatedLevel,
91                             wgpu::TextureDescriptor textureDescriptor);
92     angle::Result initExternal(angle::FormatID intendedFormatID,
93                                angle::FormatID actualFormatID,
94                                wgpu::Texture externalTexture);
95 
96     angle::Result flushStagedUpdates(ContextWgpu *contextWgpu);
97     angle::Result flushSingleLevelUpdates(ContextWgpu *contextWgpu,
98                                           gl::LevelIndex levelGL,
99                                           ClearValuesArray *deferredClears,
100                                           uint32_t deferredClearIndex);
101 
102     wgpu::TextureDescriptor createTextureDescriptor(wgpu::TextureUsage usage,
103                                                     wgpu::TextureDimension dimension,
104                                                     wgpu::Extent3D size,
105                                                     wgpu::TextureFormat format,
106                                                     std::uint32_t mipLevelCount,
107                                                     std::uint32_t sampleCount);
108 
109     angle::Result stageTextureUpload(ContextWgpu *contextWgpu,
110                                      const webgpu::Format &webgpuFormat,
111                                      GLenum type,
112                                      const gl::Extents &glExtents,
113                                      GLuint inputRowPitch,
114                                      GLuint inputDepthPitch,
115                                      uint32_t outputRowPitch,
116                                      uint32_t outputDepthPitch,
117                                      uint32_t allocationSize,
118                                      const gl::ImageIndex &index,
119                                      const uint8_t *pixels);
120 
121     void stageClear(gl::LevelIndex targetLevel,
122                     ClearValues clearValues,
123                     bool hasDepth,
124                     bool hasStencil);
125 
126     void removeStagedUpdates(gl::LevelIndex levelToRemove);
127 
128     void resetImage();
129 
130     static angle::Result getReadPixelsParams(rx::ContextWgpu *contextWgpu,
131                                              const gl::PixelPackState &packState,
132                                              gl::Buffer *packBuffer,
133                                              GLenum format,
134                                              GLenum type,
135                                              const gl::Rectangle &area,
136                                              const gl::Rectangle &clippedArea,
137                                              rx::PackPixelsParams *paramsOut,
138                                              GLuint *skipBytesOut);
139 
140     angle::Result readPixels(rx::ContextWgpu *contextWgpu,
141                              const gl::Rectangle &area,
142                              const rx::PackPixelsParams &packPixelsParams,
143                              void *pixels);
144 
145     angle::Result createTextureView(gl::LevelIndex targetLevel,
146                                     uint32_t layerIndex,
147                                     wgpu::TextureView &textureViewOut);
148     LevelIndex toWgpuLevel(gl::LevelIndex levelIndexGl) const;
149     gl::LevelIndex toGlLevel(LevelIndex levelIndexWgpu) const;
150     bool isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel);
getTexture()151     wgpu::Texture &getTexture() { return mTexture; }
toWgpuTextureFormat()152     wgpu::TextureFormat toWgpuTextureFormat() const { return mTextureDescriptor.format; }
getIntendedFormatID()153     angle::FormatID getIntendedFormatID() { return mIntendedFormatID; }
getActualFormatID()154     angle::FormatID getActualFormatID() { return mActualFormatID; }
getTextureDescriptor()155     const wgpu::TextureDescriptor &getTextureDescriptor() const { return mTextureDescriptor; }
getFirstAllocatedLevel()156     gl::LevelIndex getFirstAllocatedLevel() { return mFirstAllocatedLevel; }
157     gl::LevelIndex getLastAllocatedLevel();
getLevelCount()158     uint32_t getLevelCount() { return mTextureDescriptor.mipLevelCount; }
getSize()159     wgpu::Extent3D getSize() { return mTextureDescriptor.size; }
isInitialized()160     bool isInitialized() { return mInitialized; }
161 
162   private:
163     void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update);
164     std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level);
165 
166     wgpu::Texture mTexture;
167     wgpu::TextureDescriptor mTextureDescriptor = {};
168     bool mInitialized                          = false;
169 
170     gl::LevelIndex mFirstAllocatedLevel = gl::LevelIndex(0);
171     angle::FormatID mIntendedFormatID;
172     angle::FormatID mActualFormatID;
173 
174     std::vector<std::vector<SubresourceUpdate>> mSubresourceQueue;
175 };
176 struct BufferMapState
177 {
178     wgpu::MapMode mode;
179     size_t offset;
180     size_t size;
181 };
182 
183 enum class MapAtCreation
184 {
185     No,
186     Yes,
187 };
188 
189 class BufferHelper : public angle::NonCopyable
190 {
191   public:
192     BufferHelper();
193     ~BufferHelper();
194 
valid()195     bool valid() const { return mBuffer.operator bool(); }
196     void reset();
197 
198     angle::Result initBuffer(wgpu::Device device,
199                              size_t size,
200                              wgpu::BufferUsage usage,
201                              MapAtCreation mappedAtCreation);
202 
203     angle::Result mapImmediate(ContextWgpu *context,
204                                wgpu::MapMode mode,
205                                size_t offset,
206                                size_t size);
207     angle::Result unmap();
208 
209     uint8_t *getMapWritePointer(size_t offset, size_t size) const;
210     const uint8_t *getMapReadPointer(size_t offset, size_t size) const;
211 
212     const std::optional<BufferMapState> &getMappedState() const;
213 
214     bool canMapForRead() const;
215     bool canMapForWrite() const;
216 
217     wgpu::Buffer &getBuffer();
218     uint64_t requestedSize() const;
219     uint64_t actualSize() const;
220 
221   private:
222     wgpu::Buffer mBuffer;
223     size_t mRequestedSize = 0;
224 
225     std::optional<BufferMapState> mMappedState;
226 };
227 
228 }  // namespace webgpu
229 }  // namespace rx
230 #endif  // LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_
231