• 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 
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     VertexArrayLineLoop,
159 
160     InvalidEnum,
161     EnumCount = InvalidEnum,
162 };
163 
164 struct ClearValues
165 {
166     wgpu::Color clearColor;
167     uint32_t depthSlice;
168     float depthValue;
169     uint32_t stencilValue;
170 };
171 
172 class ClearValuesArray final
173 {
174   public:
175     ClearValuesArray();
176     ~ClearValuesArray();
177 
178     ClearValuesArray(const ClearValuesArray &other);
179     ClearValuesArray &operator=(const ClearValuesArray &rhs);
180 
181     void store(uint32_t index, const ClearValues &clearValues);
182 
183     gl::DrawBufferMask getColorMask() const;
184     void reset()
185     {
186         mValues.fill({});
187         mEnabled.reset();
188     }
189     void reset(size_t index)
190     {
191         mValues[index] = {};
192         mEnabled.reset(index);
193     }
194     void resetDepth()
195     {
196         mValues[kUnpackedDepthIndex] = {};
197         mEnabled.reset(kUnpackedDepthIndex);
198     }
199     void resetStencil()
200     {
201         mValues[kUnpackedStencilIndex] = {};
202         mEnabled.reset(kUnpackedStencilIndex);
203     }
204     const ClearValues &operator[](size_t index) const { return mValues[index]; }
205 
206     bool empty() const { return mEnabled.none(); }
207     bool any() const { return mEnabled.any(); }
208 
209     bool test(size_t index) const { return mEnabled.test(index); }
210 
211     float getDepthValue() const { return mValues[kUnpackedDepthIndex].depthValue; }
212     uint32_t getStencilValue() const { return mValues[kUnpackedStencilIndex].stencilValue; }
213     bool hasDepth() const { return mEnabled.test(kUnpackedDepthIndex); }
214     bool hasStencil() const { return mEnabled.test(kUnpackedStencilIndex); }
215 
216   private:
217     gl::AttachmentArray<ClearValues> mValues;
218     gl::AttachmentsMask mEnabled;
219 };
220 
221 void GenerateCaps(const wgpu::Limits &limitWgpu,
222                   gl::Caps *glCaps,
223                   gl::TextureCapsMap *glTextureCapsMap,
224                   gl::Extensions *glExtensions,
225                   gl::Limitations *glLimitations,
226                   egl::Caps *eglCaps,
227                   egl::DisplayExtensions *eglExtensions,
228                   gl::Version *maxSupportedESVersion);
229 
230 DisplayWgpu *GetDisplay(const gl::Context *context);
231 wgpu::Device GetDevice(const gl::Context *context);
232 wgpu::Instance GetInstance(const gl::Context *context);
233 wgpu::RenderPassColorAttachment CreateNewClearColorAttachment(wgpu::Color clearValue,
234                                                               uint32_t depthSlice,
235                                                               wgpu::TextureView textureView);
236 wgpu::RenderPassDepthStencilAttachment CreateNewDepthStencilAttachment(
237     float depthClearValue,
238     uint32_t stencilClearValue,
239     wgpu::TextureView textureView,
240     bool hasDepthValue   = false,
241     bool hasStencilValue = false);
242 
243 bool IsWgpuError(wgpu::WaitStatus waitStatus);
244 bool IsWgpuError(wgpu::MapAsyncStatus mapAsyncStatus);
245 
246 bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology topology);
247 
248 // Required alignments for buffer sizes and mapping
249 constexpr size_t kBufferSizeAlignment         = 4;
250 constexpr size_t kBufferCopyToBufferAlignment = 4;
251 constexpr size_t kBufferMapSizeAlignment   = kBufferSizeAlignment;
252 constexpr size_t kBufferMapOffsetAlignment = 8;
253 
254 // Required alignments for texture row uploads
255 constexpr size_t kTextureRowSizeAlignment = 256;
256 
257 }  // namespace webgpu
258 
259 namespace wgpu_gl
260 {
261 gl::LevelIndex getLevelIndex(webgpu::LevelIndex levelWgpu, gl::LevelIndex baseLevel);
262 gl::Extents getExtents(wgpu::Extent3D wgpuExtent);
263 }  // namespace wgpu_gl
264 
265 namespace gl_wgpu
266 {
267 webgpu::LevelIndex getLevelIndex(gl::LevelIndex levelGl, gl::LevelIndex baseLevel);
268 wgpu::TextureDimension getWgpuTextureDimension(gl::TextureType glTextureType);
269 wgpu::Extent3D getExtent3D(const gl::Extents &glExtent);
270 
271 wgpu::PrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode);
272 
273 wgpu::IndexFormat GetIndexFormat(gl::DrawElementsType drawElementsTYpe);
274 wgpu::FrontFace GetFrontFace(GLenum frontFace);
275 wgpu::CullMode GetCullMode(gl::CullFaceMode mode, bool cullFaceEnabled);
276 wgpu::ColorWriteMask GetColorWriteMask(bool r, bool g, bool b, bool a);
277 
278 wgpu::BlendFactor GetBlendFactor(gl::BlendFactorType blendFactor);
279 wgpu::BlendOperation GetBlendEquation(gl::BlendEquationType blendEquation);
280 
281 wgpu::CompareFunction GetCompareFunc(const GLenum glCompareFunc, bool testEnabled);
282 wgpu::StencilOperation getStencilOp(const GLenum glStencilOp);
283 
284 uint32_t GetFirstIndexForDrawCall(gl::DrawElementsType indexType, const void *indices);
285 }  // namespace gl_wgpu
286 
287 // Number of reserved binding slots to implement the default uniform block
288 constexpr uint32_t kReservedPerStageDefaultUniformSlotCount = 0;
289 
290 }  // namespace rx
291 
292 #define ANGLE_WGPU_WRAPPER_OBJECTS_X(PROC) \
293     PROC(BindGroup)                        \
294     PROC(Buffer)                           \
295     PROC(RenderPipeline)
296 
297 // Add a hash function for all wgpu cpp wrappers that hashes the underlying C object pointer.
298 #define ANGLE_WGPU_WRAPPER_OBJECT_HASH(OBJ)               \
299     namespace std                                         \
300     {                                                     \
301     template <>                                           \
302     struct hash<wgpu::OBJ>                                \
303     {                                                     \
304         size_t operator()(const wgpu::OBJ &wrapper) const \
305         {                                                 \
306             std::hash<decltype(wrapper.Get())> cTypeHash; \
307             return cTypeHash(wrapper.Get());              \
308         }                                                 \
309     };                                                    \
310     }
311 
312 ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_HASH)
313 #undef ANGLE_WGPU_WRAPPER_OBJECT_HASH
314 
315 // Add a hash function for all wgpu cpp wrappers that compares the underlying C object pointer.
316 #define ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY(OBJ)        \
317     namespace wgpu                                     \
318     {                                                  \
319     inline bool operator==(const OBJ &a, const OBJ &b) \
320     {                                                  \
321         return a.Get() == b.Get();                     \
322     }                                                  \
323     }
324 
325 ANGLE_WGPU_WRAPPER_OBJECTS_X(ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY)
326 #undef ANGLE_WGPU_WRAPPER_OBJECT_EQUALITY
327 
328 #undef ANGLE_WGPU_WRAPPER_OBJECTS_X
329 
330 #endif  // LIBANGLE_RENDERER_WGPU_WGPU_UTILS_H_
331