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