xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/wgpu/ContextWgpu.cpp (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 // ContextWgpu.cpp:
7 //    Implements the class methods for ContextWgpu.
8 //
9 
10 #include "libANGLE/renderer/wgpu/ContextWgpu.h"
11 
12 #include "common/debug.h"
13 
14 #include "compiler/translator/wgsl/OutputUniformBlocks.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/renderer/OverlayImpl.h"
17 #include "libANGLE/renderer/wgpu/BufferWgpu.h"
18 #include "libANGLE/renderer/wgpu/CompilerWgpu.h"
19 #include "libANGLE/renderer/wgpu/DisplayWgpu.h"
20 #include "libANGLE/renderer/wgpu/FenceNVWgpu.h"
21 #include "libANGLE/renderer/wgpu/FramebufferWgpu.h"
22 #include "libANGLE/renderer/wgpu/ImageWgpu.h"
23 #include "libANGLE/renderer/wgpu/ProgramExecutableWgpu.h"
24 #include "libANGLE/renderer/wgpu/ProgramPipelineWgpu.h"
25 #include "libANGLE/renderer/wgpu/ProgramWgpu.h"
26 #include "libANGLE/renderer/wgpu/QueryWgpu.h"
27 #include "libANGLE/renderer/wgpu/RenderbufferWgpu.h"
28 #include "libANGLE/renderer/wgpu/SamplerWgpu.h"
29 #include "libANGLE/renderer/wgpu/ShaderWgpu.h"
30 #include "libANGLE/renderer/wgpu/SyncWgpu.h"
31 #include "libANGLE/renderer/wgpu/TextureWgpu.h"
32 #include "libANGLE/renderer/wgpu/TransformFeedbackWgpu.h"
33 #include "libANGLE/renderer/wgpu/VertexArrayWgpu.h"
34 #include "libANGLE/renderer/wgpu/wgpu_pipeline_state.h"
35 #include "libANGLE/renderer/wgpu/wgpu_utils.h"
36 
37 namespace rx
38 {
39 
40 namespace
41 {
42 
43 constexpr angle::PackedEnumMap<webgpu::RenderPassClosureReason, const char *>
44     kRenderPassClosureReason = {{
45         {webgpu::RenderPassClosureReason::NewRenderPass,
46          "Render pass closed due to starting a new render pass"},
47         {webgpu::RenderPassClosureReason::FramebufferBindingChange,
48          "Render pass closed due to framebuffer binding change"},
49         {webgpu::RenderPassClosureReason::FramebufferInternalChange,
50          "Render pass closed due to framebuffer internal change"},
51         {webgpu::RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush"},
52         {webgpu::RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish"},
53         {webgpu::RenderPassClosureReason::EGLSwapBuffers,
54          "Render pass closed due to eglSwapBuffers"},
55         {webgpu::RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels"},
56         {webgpu::RenderPassClosureReason::IndexRangeReadback,
57          "Render pass closed due to index buffer read back for streamed client data"},
58         {webgpu::RenderPassClosureReason::VertexArrayStreaming,
59          "Render pass closed for uploading streamed client data"},
60     }};
61 
62 }  // namespace
63 
ContextWgpu(const gl::State & state,gl::ErrorSet * errorSet,DisplayWgpu * display)64 ContextWgpu::ContextWgpu(const gl::State &state, gl::ErrorSet *errorSet, DisplayWgpu *display)
65     : ContextImpl(state, errorSet), mDisplay(display)
66 {
67     mNewRenderPassDirtyBits = DirtyBits{
68         DIRTY_BIT_RENDER_PIPELINE_BINDING,  // The pipeline needs to be bound for each renderpass
69         DIRTY_BIT_VIEWPORT,
70         DIRTY_BIT_SCISSOR,
71         DIRTY_BIT_VERTEX_BUFFERS,
72         DIRTY_BIT_INDEX_BUFFER,
73         DIRTY_BIT_BIND_GROUPS,
74     };
75 }
76 
~ContextWgpu()77 ContextWgpu::~ContextWgpu() {}
78 
onDestroy(const gl::Context * context)79 void ContextWgpu::onDestroy(const gl::Context *context)
80 {
81     mImageLoadContext = {};
82 }
83 
initialize(const angle::ImageLoadContext & imageLoadContext)84 angle::Result ContextWgpu::initialize(const angle::ImageLoadContext &imageLoadContext)
85 {
86     mImageLoadContext = imageLoadContext;
87 
88     return angle::Result::Continue;
89 }
90 
onFramebufferChange(FramebufferWgpu * framebufferWgpu,gl::Command command)91 angle::Result ContextWgpu::onFramebufferChange(FramebufferWgpu *framebufferWgpu,
92                                                gl::Command command)
93 {
94     // If internal framebuffer state changes, always end the render pass
95     ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferInternalChange));
96 
97     return angle::Result::Continue;
98 }
99 
flush(const gl::Context * context)100 angle::Result ContextWgpu::flush(const gl::Context *context)
101 {
102     return flush(webgpu::RenderPassClosureReason::GLFlush);
103 }
104 
flush(webgpu::RenderPassClosureReason closureReason)105 angle::Result ContextWgpu::flush(webgpu::RenderPassClosureReason closureReason)
106 {
107     ANGLE_TRY(endRenderPass(closureReason));
108 
109     if (mCurrentCommandEncoder)
110     {
111         wgpu::CommandBuffer commandBuffer = mCurrentCommandEncoder.Finish();
112         mCurrentCommandEncoder            = nullptr;
113 
114         getQueue().Submit(1, &commandBuffer);
115     }
116 
117     return angle::Result::Continue;
118 }
119 
setColorAttachmentFormat(size_t colorIndex,wgpu::TextureFormat format)120 void ContextWgpu::setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format)
121 {
122     if (mRenderPipelineDesc.setColorAttachmentFormat(colorIndex, format))
123     {
124         invalidateCurrentRenderPipeline();
125     }
126 }
127 
setColorAttachmentFormats(const gl::DrawBuffersArray<wgpu::TextureFormat> & formats)128 void ContextWgpu::setColorAttachmentFormats(
129     const gl::DrawBuffersArray<wgpu::TextureFormat> &formats)
130 {
131     for (size_t i = 0; i < formats.size(); i++)
132     {
133         setColorAttachmentFormat(i, formats[i]);
134     }
135 }
136 
setDepthStencilFormat(wgpu::TextureFormat format)137 void ContextWgpu::setDepthStencilFormat(wgpu::TextureFormat format)
138 {
139     if (mRenderPipelineDesc.setDepthStencilAttachmentFormat(format))
140     {
141         invalidateCurrentRenderPipeline();
142     }
143 }
144 
setVertexAttribute(size_t attribIndex,webgpu::PackedVertexAttribute newAttrib)145 void ContextWgpu::setVertexAttribute(size_t attribIndex, webgpu::PackedVertexAttribute newAttrib)
146 {
147     if (mRenderPipelineDesc.setVertexAttribute(attribIndex, newAttrib))
148     {
149         invalidateCurrentRenderPipeline();
150     }
151 }
152 
invalidateVertexBuffer(size_t slot)153 void ContextWgpu::invalidateVertexBuffer(size_t slot)
154 {
155     if (mCurrentRenderPipelineAllAttributes[slot])
156     {
157         mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
158         mDirtyVertexBuffers.set(slot);
159     }
160 }
161 
invalidateVertexBuffers()162 void ContextWgpu::invalidateVertexBuffers()
163 {
164     mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
165     mDirtyVertexBuffers = mCurrentRenderPipelineAllAttributes;
166 }
167 
invalidateIndexBuffer()168 void ContextWgpu::invalidateIndexBuffer()
169 {
170     mDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
171 }
172 
ensureCommandEncoderCreated()173 void ContextWgpu::ensureCommandEncoderCreated()
174 {
175     if (!mCurrentCommandEncoder)
176     {
177         mCurrentCommandEncoder = getDevice().CreateCommandEncoder(nullptr);
178     }
179 }
180 
getCurrentCommandEncoder()181 wgpu::CommandEncoder &ContextWgpu::getCurrentCommandEncoder()
182 {
183     return mCurrentCommandEncoder;
184 }
185 
finish(const gl::Context * context)186 angle::Result ContextWgpu::finish(const gl::Context *context)
187 {
188     ANGLE_TRY(flush(webgpu::RenderPassClosureReason::GLFinish));
189 
190     wgpu::Future onWorkSubmittedFuture = getQueue().OnSubmittedWorkDone(
191         wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus status) {});
192     wgpu::WaitStatus status = getInstance().WaitAny(onWorkSubmittedFuture, -1);
193     ASSERT(!webgpu::IsWgpuError(status));
194 
195     return angle::Result::Continue;
196 }
197 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)198 angle::Result ContextWgpu::drawArrays(const gl::Context *context,
199                                       gl::PrimitiveMode mode,
200                                       GLint first,
201                                       GLsizei count)
202 {
203     if (mode == gl::PrimitiveMode::LineLoop)
204     {
205         UNIMPLEMENTED();
206         return angle::Result::Continue;
207     }
208     else if (mode == gl::PrimitiveMode::TriangleFan)
209     {
210         UNIMPLEMENTED();
211         return angle::Result::Continue;
212     }
213 
214     ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum, nullptr,
215                         0, nullptr));
216     mCommandBuffer.draw(static_cast<uint32_t>(count), 1, static_cast<uint32_t>(first), 0);
217     return angle::Result::Continue;
218 }
219 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount)220 angle::Result ContextWgpu::drawArraysInstanced(const gl::Context *context,
221                                                gl::PrimitiveMode mode,
222                                                GLint first,
223                                                GLsizei count,
224                                                GLsizei instanceCount)
225 {
226     if (mode == gl::PrimitiveMode::LineLoop)
227     {
228         UNIMPLEMENTED();
229         return angle::Result::Continue;
230     }
231     else if (mode == gl::PrimitiveMode::TriangleFan)
232     {
233         UNIMPLEMENTED();
234         return angle::Result::Continue;
235     }
236 
237     ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
238                         gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr));
239     mCommandBuffer.draw(static_cast<uint32_t>(count), static_cast<uint32_t>(instanceCount),
240                         static_cast<uint32_t>(first), 0);
241     return angle::Result::Continue;
242 }
243 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)244 angle::Result ContextWgpu::drawArraysInstancedBaseInstance(const gl::Context *context,
245                                                            gl::PrimitiveMode mode,
246                                                            GLint first,
247                                                            GLsizei count,
248                                                            GLsizei instanceCount,
249                                                            GLuint baseInstance)
250 {
251     if (mode == gl::PrimitiveMode::LineLoop)
252     {
253         UNIMPLEMENTED();
254         return angle::Result::Continue;
255     }
256     else if (mode == gl::PrimitiveMode::TriangleFan)
257     {
258         UNIMPLEMENTED();
259         return angle::Result::Continue;
260     }
261 
262     ANGLE_TRY(setupDraw(context, mode, first, count, instanceCount,
263                         gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr));
264     mCommandBuffer.draw(static_cast<uint32_t>(count), static_cast<uint32_t>(instanceCount),
265                         static_cast<uint32_t>(first), baseInstance);
266     return angle::Result::Continue;
267 }
268 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)269 angle::Result ContextWgpu::drawElements(const gl::Context *context,
270                                         gl::PrimitiveMode mode,
271                                         GLsizei count,
272                                         gl::DrawElementsType type,
273                                         const void *indices)
274 {
275     if (mode == gl::PrimitiveMode::LineLoop)
276     {
277         UNIMPLEMENTED();
278         return angle::Result::Continue;
279     }
280     else if (mode == gl::PrimitiveMode::TriangleFan)
281     {
282         UNIMPLEMENTED();
283         return angle::Result::Continue;
284     }
285 
286     uint32_t firstVertex = 0;
287     ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, 0, &firstVertex));
288     mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), 1, firstVertex, 0, 0);
289     return angle::Result::Continue;
290 }
291 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)292 angle::Result ContextWgpu::drawElementsBaseVertex(const gl::Context *context,
293                                                   gl::PrimitiveMode mode,
294                                                   GLsizei count,
295                                                   gl::DrawElementsType type,
296                                                   const void *indices,
297                                                   GLint baseVertex)
298 {
299     if (mode == gl::PrimitiveMode::LineLoop)
300     {
301         UNIMPLEMENTED();
302         return angle::Result::Continue;
303     }
304     else if (mode == gl::PrimitiveMode::TriangleFan)
305     {
306         UNIMPLEMENTED();
307         return angle::Result::Continue;
308     }
309 
310     uint32_t firstVertex = 0;
311     ANGLE_TRY(setupDraw(context, mode, 0, count, 1, type, indices, baseVertex, &firstVertex));
312     mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), 1, firstVertex,
313                                static_cast<uint32_t>(baseVertex), 0);
314     return angle::Result::Continue;
315 }
316 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)317 angle::Result ContextWgpu::drawElementsInstanced(const gl::Context *context,
318                                                  gl::PrimitiveMode mode,
319                                                  GLsizei count,
320                                                  gl::DrawElementsType type,
321                                                  const void *indices,
322                                                  GLsizei instances)
323 {
324     if (mode == gl::PrimitiveMode::LineLoop)
325     {
326         UNIMPLEMENTED();
327         return angle::Result::Continue;
328     }
329     else if (mode == gl::PrimitiveMode::TriangleFan)
330     {
331         UNIMPLEMENTED();
332         return angle::Result::Continue;
333     }
334 
335     uint32_t firstVertex = 0;
336     ANGLE_TRY(setupDraw(context, mode, 0, count, instances, type, indices, 0, &firstVertex));
337     mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
338                                firstVertex, 0, 0);
339     return angle::Result::Continue;
340 }
341 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)342 angle::Result ContextWgpu::drawElementsInstancedBaseVertex(const gl::Context *context,
343                                                            gl::PrimitiveMode mode,
344                                                            GLsizei count,
345                                                            gl::DrawElementsType type,
346                                                            const void *indices,
347                                                            GLsizei instances,
348                                                            GLint baseVertex)
349 {
350     if (mode == gl::PrimitiveMode::LineLoop)
351     {
352         UNIMPLEMENTED();
353         return angle::Result::Continue;
354     }
355     else if (mode == gl::PrimitiveMode::TriangleFan)
356     {
357         UNIMPLEMENTED();
358         return angle::Result::Continue;
359     }
360 
361     uint32_t firstVertex = 0;
362     ANGLE_TRY(
363         setupDraw(context, mode, 0, count, instances, type, indices, baseVertex, &firstVertex));
364     mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
365                                firstVertex, static_cast<uint32_t>(baseVertex), 0);
366     return angle::Result::Continue;
367 }
368 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)369 angle::Result ContextWgpu::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
370                                                                        gl::PrimitiveMode mode,
371                                                                        GLsizei count,
372                                                                        gl::DrawElementsType type,
373                                                                        const void *indices,
374                                                                        GLsizei instances,
375                                                                        GLint baseVertex,
376                                                                        GLuint baseInstance)
377 {
378     if (mode == gl::PrimitiveMode::LineLoop)
379     {
380         UNIMPLEMENTED();
381         return angle::Result::Continue;
382     }
383     else if (mode == gl::PrimitiveMode::TriangleFan)
384     {
385         UNIMPLEMENTED();
386         return angle::Result::Continue;
387     }
388 
389     uint32_t firstVertex = 0;
390     ANGLE_TRY(
391         setupDraw(context, mode, 0, count, instances, type, indices, baseVertex, &firstVertex));
392     mCommandBuffer.drawIndexed(static_cast<uint32_t>(count), static_cast<uint32_t>(instances),
393                                firstVertex, static_cast<uint32_t>(baseVertex),
394                                static_cast<uint32_t>(baseInstance));
395     return angle::Result::Continue;
396 }
397 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)398 angle::Result ContextWgpu::drawRangeElements(const gl::Context *context,
399                                              gl::PrimitiveMode mode,
400                                              GLuint start,
401                                              GLuint end,
402                                              GLsizei count,
403                                              gl::DrawElementsType type,
404                                              const void *indices)
405 {
406     return drawElements(context, mode, count, type, indices);
407 }
408 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)409 angle::Result ContextWgpu::drawRangeElementsBaseVertex(const gl::Context *context,
410                                                        gl::PrimitiveMode mode,
411                                                        GLuint start,
412                                                        GLuint end,
413                                                        GLsizei count,
414                                                        gl::DrawElementsType type,
415                                                        const void *indices,
416                                                        GLint baseVertex)
417 {
418     return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
419 }
420 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)421 angle::Result ContextWgpu::drawArraysIndirect(const gl::Context *context,
422                                               gl::PrimitiveMode mode,
423                                               const void *indirect)
424 {
425     UNIMPLEMENTED();
426     return angle::Result::Continue;
427 }
428 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)429 angle::Result ContextWgpu::drawElementsIndirect(const gl::Context *context,
430                                                 gl::PrimitiveMode mode,
431                                                 gl::DrawElementsType type,
432                                                 const void *indirect)
433 {
434     UNIMPLEMENTED();
435     return angle::Result::Continue;
436 }
437 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)438 angle::Result ContextWgpu::multiDrawArrays(const gl::Context *context,
439                                            gl::PrimitiveMode mode,
440                                            const GLint *firsts,
441                                            const GLsizei *counts,
442                                            GLsizei drawcount)
443 {
444     UNIMPLEMENTED();
445     return angle::Result::Continue;
446 }
447 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)448 angle::Result ContextWgpu::multiDrawArraysInstanced(const gl::Context *context,
449                                                     gl::PrimitiveMode mode,
450                                                     const GLint *firsts,
451                                                     const GLsizei *counts,
452                                                     const GLsizei *instanceCounts,
453                                                     GLsizei drawcount)
454 {
455     UNIMPLEMENTED();
456     return angle::Result::Continue;
457 }
458 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)459 angle::Result ContextWgpu::multiDrawArraysIndirect(const gl::Context *context,
460                                                    gl::PrimitiveMode mode,
461                                                    const void *indirect,
462                                                    GLsizei drawcount,
463                                                    GLsizei stride)
464 {
465     UNIMPLEMENTED();
466     return angle::Result::Continue;
467 }
468 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)469 angle::Result ContextWgpu::multiDrawElements(const gl::Context *context,
470                                              gl::PrimitiveMode mode,
471                                              const GLsizei *counts,
472                                              gl::DrawElementsType type,
473                                              const GLvoid *const *indices,
474                                              GLsizei drawcount)
475 {
476     UNIMPLEMENTED();
477     return angle::Result::Continue;
478 }
479 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)480 angle::Result ContextWgpu::multiDrawElementsInstanced(const gl::Context *context,
481                                                       gl::PrimitiveMode mode,
482                                                       const GLsizei *counts,
483                                                       gl::DrawElementsType type,
484                                                       const GLvoid *const *indices,
485                                                       const GLsizei *instanceCounts,
486                                                       GLsizei drawcount)
487 {
488     UNIMPLEMENTED();
489     return angle::Result::Continue;
490 }
491 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)492 angle::Result ContextWgpu::multiDrawElementsIndirect(const gl::Context *context,
493                                                      gl::PrimitiveMode mode,
494                                                      gl::DrawElementsType type,
495                                                      const void *indirect,
496                                                      GLsizei drawcount,
497                                                      GLsizei stride)
498 {
499     UNIMPLEMENTED();
500     return angle::Result::Continue;
501 }
502 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)503 angle::Result ContextWgpu::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
504                                                                 gl::PrimitiveMode mode,
505                                                                 const GLint *firsts,
506                                                                 const GLsizei *counts,
507                                                                 const GLsizei *instanceCounts,
508                                                                 const GLuint *baseInstances,
509                                                                 GLsizei drawcount)
510 {
511     UNIMPLEMENTED();
512     return angle::Result::Continue;
513 }
514 
multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)515 angle::Result ContextWgpu::multiDrawElementsInstancedBaseVertexBaseInstance(
516     const gl::Context *context,
517     gl::PrimitiveMode mode,
518     const GLsizei *counts,
519     gl::DrawElementsType type,
520     const GLvoid *const *indices,
521     const GLsizei *instanceCounts,
522     const GLint *baseVertices,
523     const GLuint *baseInstances,
524     GLsizei drawcount)
525 {
526     UNIMPLEMENTED();
527     return angle::Result::Continue;
528 }
529 
getResetStatus()530 gl::GraphicsResetStatus ContextWgpu::getResetStatus()
531 {
532     return gl::GraphicsResetStatus::NoError;
533 }
534 
insertEventMarker(GLsizei length,const char * marker)535 angle::Result ContextWgpu::insertEventMarker(GLsizei length, const char *marker)
536 {
537     return angle::Result::Continue;
538 }
539 
pushGroupMarker(GLsizei length,const char * marker)540 angle::Result ContextWgpu::pushGroupMarker(GLsizei length, const char *marker)
541 {
542     return angle::Result::Continue;
543 }
544 
popGroupMarker()545 angle::Result ContextWgpu::popGroupMarker()
546 {
547     return angle::Result::Continue;
548 }
549 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)550 angle::Result ContextWgpu::pushDebugGroup(const gl::Context *context,
551                                           GLenum source,
552                                           GLuint id,
553                                           const std::string &message)
554 {
555     return angle::Result::Continue;
556 }
557 
popDebugGroup(const gl::Context * context)558 angle::Result ContextWgpu::popDebugGroup(const gl::Context *context)
559 {
560     return angle::Result::Continue;
561 }
562 
syncState(const gl::Context * context,const gl::state::DirtyBits dirtyBits,const gl::state::DirtyBits bitMask,const gl::state::ExtendedDirtyBits extendedDirtyBits,const gl::state::ExtendedDirtyBits extendedBitMask,gl::Command command)563 angle::Result ContextWgpu::syncState(const gl::Context *context,
564                                      const gl::state::DirtyBits dirtyBits,
565                                      const gl::state::DirtyBits bitMask,
566                                      const gl::state::ExtendedDirtyBits extendedDirtyBits,
567                                      const gl::state::ExtendedDirtyBits extendedBitMask,
568                                      gl::Command command)
569 {
570     const gl::State &glState = context->getState();
571 
572     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
573     {
574         size_t dirtyBit = *iter;
575         switch (dirtyBit)
576         {
577             case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
578             {
579                 const FramebufferWgpu *framebufferWgpu =
580                     webgpu::GetImpl(context->getState().getDrawFramebuffer());
581                 setColorAttachmentFormats(framebufferWgpu->getCurrentColorAttachmentFormats());
582                 setDepthStencilFormat(framebufferWgpu->getCurrentDepthStencilAttachmentFormat());
583 
584                 ANGLE_TRY(endRenderPass(webgpu::RenderPassClosureReason::FramebufferBindingChange));
585             }
586             break;
587             case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
588                 break;
589             case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED:
590                 mDirtyBits.set(DIRTY_BIT_SCISSOR);
591                 break;
592             case gl::state::DIRTY_BIT_SCISSOR:
593                 mDirtyBits.set(DIRTY_BIT_SCISSOR);
594                 break;
595             case gl::state::DIRTY_BIT_VIEWPORT:
596                 mDirtyBits.set(DIRTY_BIT_VIEWPORT);
597                 break;
598             case gl::state::DIRTY_BIT_DEPTH_RANGE:
599                 mDirtyBits.set(DIRTY_BIT_VIEWPORT);
600                 break;
601             case gl::state::DIRTY_BIT_BLEND_ENABLED:
602                 break;
603             case gl::state::DIRTY_BIT_BLEND_COLOR:
604                 break;
605             case gl::state::DIRTY_BIT_BLEND_FUNCS:
606                 break;
607             case gl::state::DIRTY_BIT_BLEND_EQUATIONS:
608                 break;
609             case gl::state::DIRTY_BIT_COLOR_MASK:
610             {
611                 const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
612                 for (size_t i = 0; i < blendStateExt.getDrawBufferCount(); i++)
613                 {
614                     bool r, g, b, a;
615                     blendStateExt.getColorMaskIndexed(i, &r, &g, &b, &a);
616                     mRenderPipelineDesc.setColorWriteMask(i, r, g, b, a);
617                 }
618                 invalidateCurrentRenderPipeline();
619             }
620             break;
621             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
622                 break;
623             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
624                 break;
625             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE:
626                 break;
627             case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED:
628                 break;
629             case gl::state::DIRTY_BIT_SAMPLE_MASK:
630                 break;
631             case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED:
632                 break;
633             case gl::state::DIRTY_BIT_DEPTH_FUNC:
634                 if (mRenderPipelineDesc.setDepthFunc(
635                         gl_wgpu::getCompareFunc(glState.getDepthStencilState().depthFunc)))
636                 {
637                     invalidateCurrentRenderPipeline();
638                 }
639                 break;
640             case gl::state::DIRTY_BIT_DEPTH_MASK:
641                 break;
642             case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED:
643                 break;
644             case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT:
645                 if (mRenderPipelineDesc.setStencilFrontFunc(
646                         gl_wgpu::getCompareFunc(glState.getDepthStencilState().stencilFunc)))
647                 {
648                     invalidateCurrentRenderPipeline();
649                 }
650                 break;
651             case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK:
652                 if (mRenderPipelineDesc.setStencilBackFunc(
653                         gl_wgpu::getCompareFunc(glState.getDepthStencilState().stencilBackFunc)))
654                 {
655                     invalidateCurrentRenderPipeline();
656                 }
657                 break;
658             case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT:
659             {
660                 wgpu::StencilOperation failOp =
661                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilFail);
662                 wgpu::StencilOperation depthFailOp =
663                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilPassDepthFail);
664                 wgpu::StencilOperation passOp =
665                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilPassDepthPass);
666                 if (mRenderPipelineDesc.setStencilFrontOps(failOp, depthFailOp, passOp))
667                 {
668                     invalidateCurrentRenderPipeline();
669                 }
670             }
671             break;
672             case gl::state::DIRTY_BIT_STENCIL_OPS_BACK:
673             {
674                 wgpu::StencilOperation failOp =
675                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackFail);
676                 wgpu::StencilOperation depthFailOp =
677                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackPassDepthFail);
678                 wgpu::StencilOperation passOp =
679                     gl_wgpu::getStencilOp(glState.getDepthStencilState().stencilBackPassDepthPass);
680                 if (mRenderPipelineDesc.setStencilBackOps(failOp, depthFailOp, passOp))
681                 {
682                     invalidateCurrentRenderPipeline();
683                 }
684             }
685             break;
686             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
687                 if (mRenderPipelineDesc.setStencilWriteMask(
688                         glState.getDepthStencilState().stencilWritemask))
689                 {
690                     invalidateCurrentRenderPipeline();
691                 }
692                 break;
693             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
694                 break;
695             case gl::state::DIRTY_BIT_CULL_FACE_ENABLED:
696             case gl::state::DIRTY_BIT_CULL_FACE:
697                 mRenderPipelineDesc.setCullMode(glState.getRasterizerState().cullMode,
698                                                 glState.getRasterizerState().cullFace);
699                 invalidateCurrentRenderPipeline();
700                 break;
701             case gl::state::DIRTY_BIT_FRONT_FACE:
702                 mRenderPipelineDesc.setFrontFace(glState.getRasterizerState().frontFace);
703                 invalidateCurrentRenderPipeline();
704                 break;
705             case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
706                 break;
707             case gl::state::DIRTY_BIT_POLYGON_OFFSET:
708                 break;
709             case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
710                 break;
711             case gl::state::DIRTY_BIT_LINE_WIDTH:
712                 break;
713             case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
714                 break;
715             case gl::state::DIRTY_BIT_CLEAR_COLOR:
716                 break;
717             case gl::state::DIRTY_BIT_CLEAR_DEPTH:
718                 break;
719             case gl::state::DIRTY_BIT_CLEAR_STENCIL:
720                 break;
721             case gl::state::DIRTY_BIT_UNPACK_STATE:
722                 break;
723             case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING:
724                 break;
725             case gl::state::DIRTY_BIT_PACK_STATE:
726                 break;
727             case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING:
728                 break;
729             case gl::state::DIRTY_BIT_DITHER_ENABLED:
730                 break;
731             case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING:
732                 break;
733             case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING:
734                 invalidateCurrentRenderPipeline();
735                 break;
736             case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
737                 break;
738             case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
739                 break;
740             case gl::state::DIRTY_BIT_PROGRAM_BINDING:
741             case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
742                 invalidateCurrentRenderPipeline();
743                 break;
744             case gl::state::DIRTY_BIT_SAMPLER_BINDINGS:
745                 break;
746             case gl::state::DIRTY_BIT_TEXTURE_BINDINGS:
747                 break;
748             case gl::state::DIRTY_BIT_IMAGE_BINDINGS:
749                 break;
750             case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
751                 break;
752             case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
753                 break;
754             case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
755                 break;
756             case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
757                 break;
758             case gl::state::DIRTY_BIT_MULTISAMPLING:
759                 break;
760             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
761                 break;
762             case gl::state::DIRTY_BIT_COVERAGE_MODULATION:
763                 break;
764             case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
765                 break;
766             case gl::state::DIRTY_BIT_CURRENT_VALUES:
767                 break;
768             case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
769                 break;
770             case gl::state::DIRTY_BIT_SAMPLE_SHADING:
771                 break;
772             case gl::state::DIRTY_BIT_PATCH_VERTICES:
773                 break;
774             case gl::state::DIRTY_BIT_EXTENDED:
775             {
776                 for (auto extendedIter    = extendedDirtyBits.begin(),
777                           extendedEndIter = extendedDirtyBits.end();
778                      extendedIter != extendedEndIter; ++extendedIter)
779                 {
780                     const size_t extendedDirtyBit = *extendedIter;
781                     switch (extendedDirtyBit)
782                     {
783                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
784                             break;
785                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
786                             break;
787                         case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
788                             break;
789                         case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
790                             break;
791                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
792                             break;
793                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
794                             break;
795                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
796                             break;
797                         case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
798                             break;
799                         case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE:
800                             break;
801                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
802                             break;
803                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
804                             break;
805                         case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT:
806                             break;
807                         default:
808                             UNREACHABLE();
809                     }
810                 }
811             }
812             break;
813 
814             default:
815                 UNREACHABLE();
816                 break;
817         }
818     }
819 
820     return angle::Result::Continue;
821 }
822 
getGPUDisjoint()823 GLint ContextWgpu::getGPUDisjoint()
824 {
825     return 0;
826 }
827 
getTimestamp()828 GLint64 ContextWgpu::getTimestamp()
829 {
830     return 0;
831 }
832 
onMakeCurrent(const gl::Context * context)833 angle::Result ContextWgpu::onMakeCurrent(const gl::Context *context)
834 {
835     return angle::Result::Continue;
836 }
837 
getNativeCaps() const838 gl::Caps ContextWgpu::getNativeCaps() const
839 {
840     return mDisplay->getGLCaps();
841 }
842 
getNativeTextureCaps() const843 const gl::TextureCapsMap &ContextWgpu::getNativeTextureCaps() const
844 {
845     return mDisplay->getGLTextureCaps();
846 }
847 
getNativeExtensions() const848 const gl::Extensions &ContextWgpu::getNativeExtensions() const
849 {
850     return mDisplay->getGLExtensions();
851 }
852 
getNativeLimitations() const853 const gl::Limitations &ContextWgpu::getNativeLimitations() const
854 {
855     return mDisplay->getGLLimitations();
856 }
857 
getNativePixelLocalStorageOptions() const858 const ShPixelLocalStorageOptions &ContextWgpu::getNativePixelLocalStorageOptions() const
859 {
860     return mDisplay->getPLSOptions();
861 }
862 
createCompiler()863 CompilerImpl *ContextWgpu::createCompiler()
864 {
865     return new CompilerWgpu();
866 }
867 
createShader(const gl::ShaderState & data)868 ShaderImpl *ContextWgpu::createShader(const gl::ShaderState &data)
869 {
870     return new ShaderWgpu(data);
871 }
872 
createProgram(const gl::ProgramState & data)873 ProgramImpl *ContextWgpu::createProgram(const gl::ProgramState &data)
874 {
875     return new ProgramWgpu(data);
876 }
877 
createProgramExecutable(const gl::ProgramExecutable * executable)878 ProgramExecutableImpl *ContextWgpu::createProgramExecutable(const gl::ProgramExecutable *executable)
879 {
880     return new ProgramExecutableWgpu(executable);
881 }
882 
createFramebuffer(const gl::FramebufferState & data)883 FramebufferImpl *ContextWgpu::createFramebuffer(const gl::FramebufferState &data)
884 {
885     return new FramebufferWgpu(data);
886 }
887 
createTexture(const gl::TextureState & state)888 TextureImpl *ContextWgpu::createTexture(const gl::TextureState &state)
889 {
890     return new TextureWgpu(state);
891 }
892 
createRenderbuffer(const gl::RenderbufferState & state)893 RenderbufferImpl *ContextWgpu::createRenderbuffer(const gl::RenderbufferState &state)
894 {
895     return new RenderbufferWgpu(state);
896 }
897 
createBuffer(const gl::BufferState & state)898 BufferImpl *ContextWgpu::createBuffer(const gl::BufferState &state)
899 {
900     return new BufferWgpu(state);
901 }
902 
createVertexArray(const gl::VertexArrayState & data)903 VertexArrayImpl *ContextWgpu::createVertexArray(const gl::VertexArrayState &data)
904 {
905     return new VertexArrayWgpu(data);
906 }
907 
createQuery(gl::QueryType type)908 QueryImpl *ContextWgpu::createQuery(gl::QueryType type)
909 {
910     return new QueryWgpu(type);
911 }
912 
createFenceNV()913 FenceNVImpl *ContextWgpu::createFenceNV()
914 {
915     return new FenceNVWgpu();
916 }
917 
createSync()918 SyncImpl *ContextWgpu::createSync()
919 {
920     return new SyncWgpu();
921 }
922 
createTransformFeedback(const gl::TransformFeedbackState & state)923 TransformFeedbackImpl *ContextWgpu::createTransformFeedback(const gl::TransformFeedbackState &state)
924 {
925     return new TransformFeedbackWgpu(state);
926 }
927 
createSampler(const gl::SamplerState & state)928 SamplerImpl *ContextWgpu::createSampler(const gl::SamplerState &state)
929 {
930     return new SamplerWgpu(state);
931 }
932 
createProgramPipeline(const gl::ProgramPipelineState & state)933 ProgramPipelineImpl *ContextWgpu::createProgramPipeline(const gl::ProgramPipelineState &state)
934 {
935     return new ProgramPipelineWgpu(state);
936 }
937 
createMemoryObject()938 MemoryObjectImpl *ContextWgpu::createMemoryObject()
939 {
940     UNREACHABLE();
941     return nullptr;
942 }
943 
createSemaphore()944 SemaphoreImpl *ContextWgpu::createSemaphore()
945 {
946     UNREACHABLE();
947     return nullptr;
948 }
949 
createOverlay(const gl::OverlayState & state)950 OverlayImpl *ContextWgpu::createOverlay(const gl::OverlayState &state)
951 {
952     return new OverlayImpl(state);
953 }
954 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)955 angle::Result ContextWgpu::dispatchCompute(const gl::Context *context,
956                                            GLuint numGroupsX,
957                                            GLuint numGroupsY,
958                                            GLuint numGroupsZ)
959 {
960     return angle::Result::Continue;
961 }
962 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)963 angle::Result ContextWgpu::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
964 {
965     return angle::Result::Continue;
966 }
967 
memoryBarrier(const gl::Context * context,GLbitfield barriers)968 angle::Result ContextWgpu::memoryBarrier(const gl::Context *context, GLbitfield barriers)
969 {
970     return angle::Result::Continue;
971 }
972 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)973 angle::Result ContextWgpu::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
974 {
975     return angle::Result::Continue;
976 }
977 
handleError(GLenum errorCode,const char * message,const char * file,const char * function,unsigned int line)978 void ContextWgpu::handleError(GLenum errorCode,
979                               const char *message,
980                               const char *file,
981                               const char *function,
982                               unsigned int line)
983 {
984     std::stringstream errorStream;
985     errorStream << "Internal Wgpu back-end error: " << message << ".";
986     mErrors->handleError(errorCode, errorStream.str().c_str(), file, function, line);
987 }
988 
startRenderPass(const wgpu::RenderPassDescriptor & desc)989 angle::Result ContextWgpu::startRenderPass(const wgpu::RenderPassDescriptor &desc)
990 {
991     ensureCommandEncoderCreated();
992 
993     mCurrentRenderPass = mCurrentCommandEncoder.BeginRenderPass(&desc);
994     mDirtyBits |= mNewRenderPassDirtyBits;
995 
996     return angle::Result::Continue;
997 }
998 
endRenderPass(webgpu::RenderPassClosureReason closureReason)999 angle::Result ContextWgpu::endRenderPass(webgpu::RenderPassClosureReason closureReason)
1000 {
1001     if (mCurrentRenderPass)
1002     {
1003         const char *reasonText = kRenderPassClosureReason[closureReason];
1004         ASSERT(reasonText);
1005 
1006         if (mCommandBuffer.hasCommands())
1007         {
1008             ANGLE_WGPU_SCOPED_DEBUG_TRY(this, mCommandBuffer.recordCommands(mCurrentRenderPass));
1009             mCommandBuffer.clear();
1010         }
1011 
1012         mCurrentRenderPass.End();
1013         mCurrentRenderPass = nullptr;
1014     }
1015 
1016     mDirtyBits.set(DIRTY_BIT_RENDER_PASS);
1017 
1018     return angle::Result::Continue;
1019 }
1020 
setupDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertexOrInvalid,GLsizei vertexOrIndexCount,GLsizei instanceCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,GLint baseVertex,uint32_t * outFirstIndex)1021 angle::Result ContextWgpu::setupDraw(const gl::Context *context,
1022                                      gl::PrimitiveMode mode,
1023                                      GLint firstVertexOrInvalid,
1024                                      GLsizei vertexOrIndexCount,
1025                                      GLsizei instanceCount,
1026                                      gl::DrawElementsType indexTypeOrInvalid,
1027                                      const void *indices,
1028                                      GLint baseVertex,
1029                                      uint32_t *outFirstIndex)
1030 {
1031     if (mRenderPipelineDesc.setPrimitiveMode(mode, indexTypeOrInvalid))
1032     {
1033         invalidateCurrentRenderPipeline();
1034     }
1035 
1036     ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable());
1037     if (executableWgpu->checkDirtyUniforms())
1038     {
1039         mDirtyBits.set(DIRTY_BIT_BIND_GROUPS);
1040     }
1041 
1042     const void *adjustedIndicesPtr = indices;
1043     if (mState.areClientArraysEnabled())
1044     {
1045         VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
1046         ANGLE_TRY(vertexArrayWgpu->syncClientArrays(
1047             context, mState.getProgramExecutable()->getActiveAttribLocationsMask(),
1048             firstVertexOrInvalid, vertexOrIndexCount, instanceCount, indexTypeOrInvalid, indices,
1049             baseVertex, mState.isPrimitiveRestartEnabled(), &adjustedIndicesPtr));
1050     }
1051 
1052     bool reAddDirtyIndexBufferBit = false;
1053     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
1054     {
1055         *outFirstIndex = gl_wgpu::GetFirstIndexForDrawCall(indexTypeOrInvalid, adjustedIndicesPtr);
1056         if (mCurrentIndexBufferType != indexTypeOrInvalid)
1057         {
1058             invalidateIndexBuffer();
1059         }
1060     }
1061     else
1062     {
1063         ASSERT(outFirstIndex == nullptr);
1064     }
1065 
1066     if (mDirtyBits.any())
1067     {
1068         for (DirtyBits::Iterator dirtyBitIter = mDirtyBits.begin();
1069              dirtyBitIter != mDirtyBits.end(); ++dirtyBitIter)
1070         {
1071             size_t dirtyBit = *dirtyBitIter;
1072             switch (dirtyBit)
1073             {
1074                 case DIRTY_BIT_RENDER_PIPELINE_DESC:
1075                     ANGLE_TRY(handleDirtyRenderPipelineDesc(&dirtyBitIter));
1076                     break;
1077 
1078                 case DIRTY_BIT_RENDER_PASS:
1079                     ANGLE_TRY(handleDirtyRenderPass(&dirtyBitIter));
1080                     break;
1081 
1082                 case DIRTY_BIT_RENDER_PIPELINE_BINDING:
1083                     ANGLE_TRY(handleDirtyRenderPipelineBinding(&dirtyBitIter));
1084                     break;
1085 
1086                 case DIRTY_BIT_VIEWPORT:
1087                     ANGLE_TRY(handleDirtyViewport(&dirtyBitIter));
1088                     break;
1089 
1090                 case DIRTY_BIT_SCISSOR:
1091                     ANGLE_TRY(handleDirtyScissor(&dirtyBitIter));
1092                     break;
1093 
1094                 case DIRTY_BIT_VERTEX_BUFFERS:
1095                     ANGLE_TRY(handleDirtyVertexBuffers(mDirtyVertexBuffers, &dirtyBitIter));
1096                     mDirtyVertexBuffers.reset();
1097                     break;
1098 
1099                 case DIRTY_BIT_INDEX_BUFFER:
1100                     if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
1101                     {
1102                         ANGLE_TRY(handleDirtyIndexBuffer(indexTypeOrInvalid, &dirtyBitIter));
1103                     }
1104                     else
1105                     {
1106                         // If this is not an indexed draw call, don't sync the index buffer. Save it
1107                         // for a future indexed draw call when we know what index type to use
1108                         reAddDirtyIndexBufferBit = true;
1109                     }
1110                     break;
1111                 case DIRTY_BIT_BIND_GROUPS:
1112                     ANGLE_TRY(handleDirtyBindGroups(&dirtyBitIter));
1113                     break;
1114                 default:
1115                     UNREACHABLE();
1116                     break;
1117             }
1118         }
1119 
1120         if (reAddDirtyIndexBufferBit)
1121         {
1122             // Re-add the index buffer dirty bit for a future indexed draw call.
1123             mDirtyBits.reset(DIRTY_BIT_INDEX_BUFFER);
1124         }
1125 
1126         mDirtyBits.reset();
1127     }
1128 
1129     return angle::Result::Continue;
1130 }
1131 
handleDirtyRenderPipelineDesc(DirtyBits::Iterator * dirtyBitsIterator)1132 angle::Result ContextWgpu::handleDirtyRenderPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
1133 {
1134     ASSERT(mState.getProgramExecutable() != nullptr);
1135     ProgramExecutableWgpu *executable = webgpu::GetImpl(mState.getProgramExecutable());
1136     ASSERT(executable);
1137 
1138     wgpu::RenderPipeline previousPipeline = std::move(mCurrentGraphicsPipeline);
1139     ANGLE_TRY(executable->getRenderPipeline(this, mRenderPipelineDesc, &mCurrentGraphicsPipeline));
1140     if (mCurrentGraphicsPipeline != previousPipeline)
1141     {
1142         dirtyBitsIterator->setLaterBit(DIRTY_BIT_RENDER_PIPELINE_BINDING);
1143     }
1144     mCurrentRenderPipelineAllAttributes =
1145         executable->getExecutable()->getActiveAttribLocationsMask();
1146 
1147     return angle::Result::Continue;
1148 }
1149 
handleDirtyRenderPipelineBinding(DirtyBits::Iterator * dirtyBitsIterator)1150 angle::Result ContextWgpu::handleDirtyRenderPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator)
1151 {
1152     ASSERT(mCurrentGraphicsPipeline);
1153     mCommandBuffer.setPipeline(mCurrentGraphicsPipeline);
1154     return angle::Result::Continue;
1155 }
1156 
handleDirtyViewport(DirtyBits::Iterator * dirtyBitsIterator)1157 angle::Result ContextWgpu::handleDirtyViewport(DirtyBits::Iterator *dirtyBitsIterator)
1158 {
1159     const gl::Framebuffer *framebuffer = mState.getDrawFramebuffer();
1160     const gl::Extents &framebufferSize = framebuffer->getExtents();
1161     const gl::Rectangle framebufferRect(0, 0, framebufferSize.width, framebufferSize.height);
1162 
1163     gl::Rectangle clampedViewport;
1164     if (!ClipRectangle(mState.getViewport(), framebufferRect, &clampedViewport))
1165     {
1166         clampedViewport = gl::Rectangle(0, 0, 1, 1);
1167     }
1168 
1169     float depthMin = mState.getNearPlane();
1170     float depthMax = mState.getFarPlane();
1171 
1172     // This clamping should be done by the front end. WebGPU requires values in this range.
1173     ASSERT(depthMin >= 0 && depthMin <= 1);
1174     ASSERT(depthMin >= 0 && depthMin <= 1);
1175 
1176     // WebGPU requires that the maxDepth is at least minDepth. WebGL requires the same but core GL
1177     // ES does not.
1178     if (depthMin > depthMax)
1179     {
1180         UNIMPLEMENTED();
1181     }
1182 
1183     bool isDefaultViewport = (clampedViewport == framebufferRect) && depthMin == 0 && depthMax == 1;
1184     if (isDefaultViewport && !mCommandBuffer.hasSetViewportCommand())
1185     {
1186         // Each render pass has a default viewport set equal to the size of the render targets. We
1187         // can skip setting the viewport.
1188         return angle::Result::Continue;
1189     }
1190 
1191     ASSERT(mCurrentGraphicsPipeline);
1192     mCommandBuffer.setViewport(clampedViewport.x, clampedViewport.y, clampedViewport.width,
1193                                clampedViewport.height, depthMin, depthMax);
1194     return angle::Result::Continue;
1195 }
1196 
handleDirtyScissor(DirtyBits::Iterator * dirtyBitsIterator)1197 angle::Result ContextWgpu::handleDirtyScissor(DirtyBits::Iterator *dirtyBitsIterator)
1198 {
1199     const gl::Framebuffer *framebuffer = mState.getDrawFramebuffer();
1200     const gl::Extents &framebufferSize = framebuffer->getExtents();
1201     const gl::Rectangle framebufferRect(0, 0, framebufferSize.width, framebufferSize.height);
1202 
1203     gl::Rectangle clampedScissor = framebufferRect;
1204 
1205     // When the GL scissor test is disabled, set the scissor to the entire size of the framebuffer
1206     if (mState.isScissorTestEnabled())
1207     {
1208         if (!ClipRectangle(mState.getScissor(), framebufferRect, &clampedScissor))
1209         {
1210             clampedScissor = gl::Rectangle(0, 0, 0, 0);
1211         }
1212     }
1213 
1214     bool isDefaultScissor = clampedScissor == framebufferRect;
1215     if (isDefaultScissor && !mCommandBuffer.hasSetScissorCommand())
1216     {
1217         // Each render pass has a default scissor set equal to the size of the render targets. We
1218         // can skip setting the scissor.
1219         return angle::Result::Continue;
1220     }
1221 
1222     ASSERT(mCurrentGraphicsPipeline);
1223     mCommandBuffer.setScissorRect(clampedScissor.x, clampedScissor.y, clampedScissor.width,
1224                                   clampedScissor.height);
1225     return angle::Result::Continue;
1226 }
1227 
handleDirtyRenderPass(DirtyBits::Iterator * dirtyBitsIterator)1228 angle::Result ContextWgpu::handleDirtyRenderPass(DirtyBits::Iterator *dirtyBitsIterator)
1229 {
1230     FramebufferWgpu *drawFramebufferWgpu = webgpu::GetImpl(mState.getDrawFramebuffer());
1231     ANGLE_TRY(drawFramebufferWgpu->startNewRenderPass(this));
1232     dirtyBitsIterator->setLaterBits(mNewRenderPassDirtyBits);
1233     mDirtyVertexBuffers = mCurrentRenderPipelineAllAttributes;
1234     return angle::Result::Continue;
1235 }
1236 
handleDirtyVertexBuffers(const gl::AttributesMask & slots,DirtyBits::Iterator * dirtyBitsIterator)1237 angle::Result ContextWgpu::handleDirtyVertexBuffers(const gl::AttributesMask &slots,
1238                                                     DirtyBits::Iterator *dirtyBitsIterator)
1239 {
1240     VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
1241     for (size_t slot : slots)
1242     {
1243         webgpu::BufferHelper *buffer = vertexArrayWgpu->getVertexBuffer(slot);
1244         if (!buffer)
1245         {
1246             // Missing default attribute support
1247             ASSERT(!mState.getVertexArray()->getVertexAttribute(slot).enabled);
1248             UNIMPLEMENTED();
1249             continue;
1250         }
1251         if (buffer->getMappedState())
1252         {
1253             ANGLE_TRY(buffer->unmap());
1254         }
1255         mCommandBuffer.setVertexBuffer(static_cast<uint32_t>(slot), buffer->getBuffer());
1256     }
1257     return angle::Result::Continue;
1258 }
1259 
handleDirtyIndexBuffer(gl::DrawElementsType indexType,DirtyBits::Iterator * dirtyBitsIterator)1260 angle::Result ContextWgpu::handleDirtyIndexBuffer(gl::DrawElementsType indexType,
1261                                                   DirtyBits::Iterator *dirtyBitsIterator)
1262 {
1263     VertexArrayWgpu *vertexArrayWgpu = GetImplAs<VertexArrayWgpu>(mState.getVertexArray());
1264     webgpu::BufferHelper *buffer     = vertexArrayWgpu->getIndexBuffer();
1265     ASSERT(buffer);
1266     if (buffer->getMappedState())
1267     {
1268         ANGLE_TRY(buffer->unmap());
1269     }
1270     mCommandBuffer.setIndexBuffer(buffer->getBuffer(), gl_wgpu::GetIndexFormat(indexType), 0, -1);
1271     mCurrentIndexBufferType = indexType;
1272     return angle::Result::Continue;
1273 }
1274 
handleDirtyBindGroups(DirtyBits::Iterator * dirtyBitsIterator)1275 angle::Result ContextWgpu::handleDirtyBindGroups(DirtyBits::Iterator *dirtyBitsIterator)
1276 {
1277     ProgramExecutableWgpu *executableWgpu = webgpu::GetImpl(mState.getProgramExecutable());
1278     wgpu::BindGroup bindGroup;
1279     ANGLE_TRY(executableWgpu->updateUniformsAndGetBindGroup(this, &bindGroup));
1280     // TODO(anglebug.com/376553328): need to set up every bind group here.
1281     mCommandBuffer.setBindGroup(sh::kDefaultUniformBlockBindGroup, bindGroup);
1282 
1283     return angle::Result::Continue;
1284 }
1285 
1286 }  // namespace rx
1287