xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/wgpu/wgpu_utils.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_UTILS_H_
8 #define LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_
9 
10 #include <dawn/webgpu_cpp.h>
11 #include <stdint.h>
12 #include <climits>
13 
14 #include "libANGLE/Caps.h"
15 #include "libANGLE/Error.h"
16 #include "libANGLE/angletypes.h"
17 
18 #define ANGLE_WGPU_TRY(context, command)                                                     \
19     do                                                                                       \
20     {                                                                                        \
21         auto ANGLE_LOCAL_VAR = command;                                                      \
22         if (ANGLE_UNLIKELY(::rx::webgpu::IsWgpuError(ANGLE_LOCAL_VAR)))                      \
23         {                                                                                    \
24             (context)->handleError(GL_INVALID_OPERATION, "Internal WebGPU error.", __FILE__, \
25                                    ANGLE_FUNCTION, __LINE__);                                \
26             return angle::Result::Stop;                                                      \
27         }                                                                                    \
28     } while (0)
29 
30 #define ANGLE_WGPU_BEGIN_DEBUG_ERROR_SCOPE(context)                             \
31     ::rx::webgpu::DebugErrorScope(context->getInstance(), context->getDevice(), \
32                                   wgpu::ErrorFilter::Validation)
33 #define ANGLE_WGPU_END_DEBUG_ERROR_SCOPE(context, scope) \
34     ANGLE_TRY(scope.PopScope(context, __FILE__, ANGLE_FUNCTION, __LINE__))
35 
36 #define ANGLE_WGPU_SCOPED_DEBUG_TRY(context, command)                                            \
37     do                                                                                           \
38     {                                                                                            \
39         ::rx::webgpu::DebugErrorScope _errorScope = ANGLE_WGPU_BEGIN_DEBUG_ERROR_SCOPE(context); \
40         (command);                                                                               \
41         ANGLE_WGPU_END_DEBUG_ERROR_SCOPE(context, _errorScope);                                  \
42     } while (0)
43 
44 #define ANGLE_GL_OBJECTS_X(PROC) \
45     PROC(Buffer)                 \
46     PROC(Context)                \
47     PROC(Framebuffer)            \
48     PROC(Query)                  \
49     PROC(Program)                \
50     PROC(ProgramExecutable)      \
51     PROC(Sampler)                \
52     PROC(Texture)                \
53     PROC(TransformFeedback)      \
54     PROC(VertexArray)
55 
56 #define ANGLE_EGL_OBJECTS_X(PROC) \
57     PROC(Display)                 \
58     PROC(Image)                   \
59     PROC(Surface)                 \
60     PROC(Sync)
61 
62 namespace rx
63 {
64 
65 class ContextWgpu;
66 class DisplayWgpu;
67 
68 #define ANGLE_PRE_DECLARE_WGPU_OBJECT(OBJ) class OBJ##Wgpu;
69 
70 ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_WGPU_OBJECT)
ANGLE_EGL_OBJECTS_X(ANGLE_PRE_DECLARE_WGPU_OBJECT)71 ANGLE_EGL_OBJECTS_X(ANGLE_PRE_DECLARE_WGPU_OBJECT)
72 
73 namespace webgpu
74 {
75 template <typename T>
76 struct ImplTypeHelper;
77 
78 #define ANGLE_IMPL_TYPE_HELPER(frontendNamespace, OBJ) \
79     template <>                                        \
80     struct ImplTypeHelper<frontendNamespace::OBJ>      \
81     {                                                  \
82         using ImplType = rx::OBJ##Wgpu;                \
83     };
84 #define ANGLE_IMPL_TYPE_HELPER_GL(OBJ) ANGLE_IMPL_TYPE_HELPER(gl, OBJ)
85 #define ANGLE_IMPL_TYPE_HELPER_EGL(OBJ) ANGLE_IMPL_TYPE_HELPER(egl, OBJ)
86 
87 ANGLE_GL_OBJECTS_X(ANGLE_IMPL_TYPE_HELPER_GL)
88 ANGLE_EGL_OBJECTS_X(ANGLE_IMPL_TYPE_HELPER_EGL)
89 
90 #undef ANGLE_IMPL_TYPE_HELPER_GL
91 #undef ANGLE_IMPL_TYPE_HELPER_EGL
92 
93 template <typename T>
94 using GetImplType = typename ImplTypeHelper<T>::ImplType;
95 
96 template <typename T>
97 GetImplType<T> *GetImpl(const T *glObject)
98 {
99     return GetImplAs<GetImplType<T>>(glObject);
100 }
101 
102 constexpr size_t kUnpackedDepthIndex   = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
103 constexpr size_t kUnpackedStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
104 constexpr uint32_t kUnpackedColorBuffersMask =
105     angle::BitMask<uint32_t>(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
106 // WebGPU image level index.
107 using LevelIndex = gl::LevelIndexWrapper<uint32_t>;
108 
109 class ErrorScope : public angle::NonCopyable
110 {
111   public:
112     ErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType);
113     ~ErrorScope();
114 
115     angle::Result PopScope(ContextWgpu *context,
116                            const char *file,
117                            const char *function,
118                            unsigned int line);
119 
120   private:
121     wgpu::Instance mInstance;
122     wgpu::Device mDevice;
123     bool mActive = false;
124 };
125 
126 class NoOpErrorScope : public angle::NonCopyable
127 {
128   public:
129     NoOpErrorScope(wgpu::Instance instance, wgpu::Device device, wgpu::ErrorFilter errorType) {}
130     ~NoOpErrorScope() {}
131 
132     angle::Result PopScope(ContextWgpu *context,
133                            const char *file,
134                            const char *function,
135                            unsigned int line)
136     {
137         return angle::Result::Continue;
138     }
139 };
140 
141 #if defined(ANGLE_ENABLE_ASSERTS)
142 using DebugErrorScope = ErrorScope;
143 #else
144 using DebugErrorScope = NoOpErrorScope;
145 #endif
146 
147 enum class RenderPassClosureReason
148 {
149     NewRenderPass,
150     FramebufferBindingChange,
151     FramebufferInternalChange,
152     GLFlush,
153     GLFinish,
154     EGLSwapBuffers,
155     GLReadPixels,
156     IndexRangeReadback,
157     VertexArrayStreaming,
158 
159     InvalidEnum,
160     EnumCount = InvalidEnum,
161 };
162 
163 struct ClearValues
164 {
165     wgpu::Color clearColor;
166     uint32_t depthSlice;
167     float depthValue;
168     uint32_t stencilValue;
169 };
170 
171 class ClearValuesArray final
172 {
173   public:
174     ClearValuesArray();
175     ~ClearValuesArray();
176 
177     ClearValuesArray(const ClearValuesArray &other);
178     ClearValuesArray &operator=(const ClearValuesArray &rhs);
179 
180     void store(uint32_t index, const ClearValues &clearValues);
181 
182     gl::DrawBufferMask getColorMask() const;
183     void reset()
184     {
185         mValues.fill({});
186         mEnabled.reset();
187     }
188     void reset(size_t index)
189     {
190         mValues[index] = {};
191         mEnabled.reset(index);
192     }
193     void resetDepth()
194     {
195         mValues[kUnpackedDepthIndex] = {};
196         mEnabled.reset(kUnpackedDepthIndex);
197     }
198     void resetStencil()
199     {
200         mValues[kUnpackedStencilIndex] = {};
201         mEnabled.reset(kUnpackedStencilIndex);
202     }
203     const ClearValues &operator[](size_t index) const { return mValues[index]; }
204 
205     bool empty() const { return mEnabled.none(); }
206     bool any() const { return mEnabled.any(); }
207 
208     bool test(size_t index) const { return mEnabled.test(index); }
209 
210     float getDepthValue() const { return mValues[kUnpackedDepthIndex].depthValue; }
211     uint32_t getStencilValue() const { return mValues[kUnpackedStencilIndex].stencilValue; }
212     bool hasDepth() const { return mEnabled.test(kUnpackedDepthIndex); }
213     bool hasStencil() const { return mEnabled.test(kUnpackedStencilIndex); }
214 
215   private:
216     gl::AttachmentArray<ClearValues> mValues;
217     gl::AttachmentsMask mEnabled;
218 };
219 
220 void GenerateCaps(const wgpu::Limits &limitWgpu,
221                   gl::Caps *glCaps,
222                   gl::TextureCapsMap *glTextureCapsMap,
223                   gl::Extensions *glExtensions,
224                   gl::Limitations *glLimitations,
225                   egl::Caps *eglCaps,
226                   egl::DisplayExtensions *eglExtensions,
227                   gl::Version *maxSupportedESVersion);
228 
229 DisplayWgpu *GetDisplay(const gl::Context *context);
230 wgpu::Device GetDevice(const gl::Context *context);
231 wgpu::Instance GetInstance(const gl::Context *context);
232 wgpu::RenderPassColorAttachment CreateNewClearColorAttachment(wgpu::Color clearValue,
233                                                               uint32_t depthSlice,
234                                                               wgpu::TextureView textureView);
235 wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment(
236     float depthClearValue,
237     uint32_t stencilClearValue,
238     wgpu::TextureView textureView,
239     bool hasDepthValue   = false,
240     bool hasStencilValue = false);
241 
242 bool IsWgpuError(wgpu::WaitStatus waitStatus);
243 bool IsWgpuError(WGPUBufferMapAsyncStatus mapBufferStatus);
244 
245 bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology);
246 
247 // Required alignments for buffer sizes and mapping
248 constexpr size_t kBufferSizeAlignment         = 4;
249 constexpr size_t kBufferCopyToBufferAlignment = 4;
250 constexpr size_t kBufferMapSizeAlignment   = kBufferSizeAlignment;
251 constexpr size_t kBufferMapOffsetAlignment = 8;
252 
253 // Required alignments for texture row uploads
254 constexpr size_t kTextureRowSizeAlignment = 256;
255 
256 }  // namespace webgpu
257 
258 namespace wgpu_gl
259 {
260 gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel);
261 gl::Extents getExtents(wgpu::Extent3D wgpuExtent);
262 }  // namespace wgpu_gl
263 
264 namespace gl_wgpu
265 {
266 webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLevel);
267 wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType);
268 wgpu::Extent3D getExtent3D(const gl::Extents &glExtent);
269 
270 wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode);
271 
272 wgpu::IndexFormat GetIndexFormat(gl::DrawElementsType drawElementsTYpe);
273 wgpu::FrontFace GetFrontFace(GLenum frontFace);
274 wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled);
275 wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a);
276 
277 wgpu::CompareFunction getCompareFunc(const GLenum glCompareFunc);
278 wgpu::StencilOperation getStencilOp(const GLenum glStencilOp);
279 
280 uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices);
281 }  // namespace gl_wgpu
282 
283 // Number of reserved binding slots to implement the default uniform block
284 constexpr uint32_t kReservedPerStageDefaultUniformSlotCount = 0;
285 
286 }  // namespace rx
287 
288 #define ANGLE_WGPU_WRAPPER_OBJECTS_X(PROC) \
289     PROC(BindGroup)                        \
290     PROC(Buffer)                           \
291     PROC(RenderPipeline)
292 
293 // Add a hash function for all wgpu cpp wrappers that hashes the underlying C object pointer.
294 #define ANGLE_WGPU_WRAPPER_OBJECT_HASH(OBJ)               \
295     namespace std                                         \
296     {                                                     \
297     template <>                                           \
298     struct hash<wgpu::OBJ>                                \
299     {                                                     \
300         size_t operator()(const wgpu::OBJ &wrapper) const \
301         {                                                 \
302             std::hash<decltype(wrapper.Get())> cTypeHash; \
303             return cTypeHash(wrapper.Get());              \
304         }                                                 \
305     };                                                    \
306     }
307 
308 ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_HASH)
309 #undef ANGLE_WGPU_WRAPPER_OBJECT_HASH
310 
311 // Add a hash function for all wgpu cpp wrappers that compares the underlying C object pointer.
312 #define ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY(OBJ)        \
313     namespace wgpu                                     \
314     {                                                  \
315     inline bool operator==(const OBJ &a, const OBJ &b) \
316     {                                                  \
317         return a.Get() == b.Get();                     \
318     }                                                  \
319     }
320 
321 ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY)
322 #undef ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY
323 
324 #undef ANGLE_WGPU_WRAPPER_OBJECTS_X
325 
326 #endif  // LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_
327