Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 0914bda141cdce2217b6663d0c0dc48fb88d1f1b
      
https://github.com/WebKit/WebKit/commit/0914bda141cdce2217b6663d0c0dc48fb88d1f1b
  Author: Kristian Monsen <[email protected]>
  Date:   2026-09-29 (Tue, 29 Sep 2026)

  Changed paths:
    A LayoutTests/fast/canvas/webgl/line-loop-draw-no-op-crash-expected.txt
    A LayoutTests/fast/canvas/webgl/line-loop-draw-no-op-crash.html
    M Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h
    M Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm
    M Source/ThirdParty/ANGLE/src/tests/gl_tests/LineLoopTest.cpp

  Log Message:
  -----------
  ANGLE: Metal: LINE_LOOP closing segment is drawn with no render pipeline 
state after a no-op draw
https://bugs.webkit.org/show_bug.cgi?id=324491
rdar://186898783

Reviewed by Kimmo Kinnunen.

LINE_LOOP is emulated as a line strip plus a separate indexed draw for the
closing segment. That segment's index buffer must be generated before the render
pass starts, so LineLoopLastSegmentHelper builds it in begin() and drew it from
its destructor, after the main draw -- unconditionally. When no enabled draw
buffer has an attachment (e.g. a complete framebuffer whose only attachment is
COLOR_ATTACHMENT1 while draw buffer 0 is COLOR_ATTACHMENT0), setupDraw()
classifies the draw as a no-op and never sets a render pipeline state, so the
closing segment was recorded as a draw call on an encoder with no pipeline 
state.

Have drawArraysImpl()/drawElementsImpl() report whether they issued a draw call,
and draw the closing segment from an explicit drawLastSegment() call on that 
path
only. Inferring it from RenderCommandEncoder::hasPipelineState() is not enough: 
a
transform feedback pass sets a pipeline state while rasterization is disabled, 
so
an encoder can hold one even when later draws are no-ops.

Two ANGLE end2end tests cover both directions of the change.
LineLoopWithNothingBoundToDrawBufferZero is the crash case; it aborts in
LineLoopLastSegmentHelper's destructor without the fix. 
LineLoopClosingSegmentIntoFramebuffer
guards against the inverse regression, where isNoOpOut comes back true when a 
draw
was in fact issued and the closing segment silently disappears: it draws a 
LINE_LOOP
square into an 8x8 FBO with the vertices ordered so that the left edge is 
covered
only by the closing segment, and reads back two texels on that edge.

The isNoOpOut contract holds because every early return in drawArraysImpl() and
drawElementsImpl() that bypasses the assignment is unreachable for the nested
LineStrip draw: LineStrip is not a polygon mode, it is neither TriangleFan nor
LineLoop, and requiresIndexRewrite() does not depend on the primitive mode 
beyond
"not Points", so if it were true the outer LINE_LOOP call would have taken
drawArraysProvokingVertexImpl() and never reached the line loop helper.

Test: fast/canvas/webgl/line-loop-draw-no-op-crash.html

* LayoutTests/fast/canvas/webgl/line-loop-draw-no-op-crash-expected.txt: Added.
* LayoutTests/fast/canvas/webgl/line-loop-draw-no-op-crash.html: Added.
* Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.mm:
(rx::ContextMtl::drawLineLoopArraysNonInstanced):
(rx::ContextMtl::drawArraysImpl):
(rx::ContextMtl::drawLineLoopElementsNonInstancedNoPrimitiveRestart):
(rx::ContextMtl::drawElementsImpl):
* Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/ContextMtl.h:
* Source/ThirdParty/ANGLE/src/tests/gl_tests/LineLoopTest.cpp:
(TEST_P):

Canonical link: https://commits.webkit.org/322177@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to