Title: [270253] trunk/Source/WebCore
Revision
270253
Author
[email protected]
Date
2020-11-30 11:20:52 -0800 (Mon, 30 Nov 2020)

Log Message

[WebGL2] Rasterizer discard interferes with implicit clears
https://bugs.webkit.org/show_bug.cgi?id=219061

Patch by Kenneth Russell <[email protected]> on 2020-11-30
Reviewed by Dean Jackson.

When rasterizer discard is enabled, user-level draw calls and
clears skip the implicit clear since they have no effect.
Readbacks and copies still perform the implicit clear.

A new WebGL conformance test has been added for this in
https://github.com/KhronosGroup/WebGL/pull/3183 which passes with
this fix. WebKit's TestRunner doesn't run the composite phase as
the browser or MiniBrowser do, so wouldn't pass this test as
integrated as a layout test. Per discussion with dino and
kkinnunen on Slack, will address this in follow-on work.

* html/canvas/WebGL2RenderingContext.cpp:
(WebCore::WebGL2RenderingContext::copyTexSubImage3D):
(WebCore::WebGL2RenderingContext::readPixels):
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::ScopedDisableRasterizerDiscard::ScopedDisableRasterizerDiscard):
(WebCore::ScopedDisableRasterizerDiscard::~ScopedDisableRasterizerDiscard):
(WebCore::WebGLRenderingContextBase::initializeNewContext):
(WebCore::WebGLRenderingContextBase::clearIfComposited):
(WebCore::WebGLRenderingContextBase::paintRenderingResultsToCanvas):
(WebCore::WebGLRenderingContextBase::paintRenderingResultsToImageData):
(WebCore::WebGLRenderingContextBase::clear):
(WebCore::WebGLRenderingContextBase::copyTexSubImage2D):
(WebCore::WebGLRenderingContextBase::disable):
(WebCore::WebGLRenderingContextBase::drawArrays):
(WebCore::WebGLRenderingContextBase::drawElements):
(WebCore::WebGLRenderingContextBase::enable):
(WebCore::WebGLRenderingContextBase::readPixels):
(WebCore::WebGLRenderingContextBase::copyTexImage2D):
(WebCore::WebGLRenderingContextBase::drawArraysInstanced):
(WebCore::WebGLRenderingContextBase::drawElementsInstanced):
* html/canvas/WebGLRenderingContextBase.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (270252 => 270253)


--- trunk/Source/WebCore/ChangeLog	2020-11-30 19:08:40 UTC (rev 270252)
+++ trunk/Source/WebCore/ChangeLog	2020-11-30 19:20:52 UTC (rev 270253)
@@ -1,3 +1,43 @@
+2020-11-30  Kenneth Russell  <[email protected]>
+
+        [WebGL2] Rasterizer discard interferes with implicit clears
+        https://bugs.webkit.org/show_bug.cgi?id=219061
+
+        Reviewed by Dean Jackson.
+
+        When rasterizer discard is enabled, user-level draw calls and
+        clears skip the implicit clear since they have no effect.
+        Readbacks and copies still perform the implicit clear.
+
+        A new WebGL conformance test has been added for this in
+        https://github.com/KhronosGroup/WebGL/pull/3183 which passes with
+        this fix. WebKit's TestRunner doesn't run the composite phase as
+        the browser or MiniBrowser do, so wouldn't pass this test as
+        integrated as a layout test. Per discussion with dino and
+        kkinnunen on Slack, will address this in follow-on work.
+
+        * html/canvas/WebGL2RenderingContext.cpp:
+        (WebCore::WebGL2RenderingContext::copyTexSubImage3D):
+        (WebCore::WebGL2RenderingContext::readPixels):
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::ScopedDisableRasterizerDiscard::ScopedDisableRasterizerDiscard):
+        (WebCore::ScopedDisableRasterizerDiscard::~ScopedDisableRasterizerDiscard):
+        (WebCore::WebGLRenderingContextBase::initializeNewContext):
+        (WebCore::WebGLRenderingContextBase::clearIfComposited):
+        (WebCore::WebGLRenderingContextBase::paintRenderingResultsToCanvas):
+        (WebCore::WebGLRenderingContextBase::paintRenderingResultsToImageData):
+        (WebCore::WebGLRenderingContextBase::clear):
+        (WebCore::WebGLRenderingContextBase::copyTexSubImage2D):
+        (WebCore::WebGLRenderingContextBase::disable):
+        (WebCore::WebGLRenderingContextBase::drawArrays):
+        (WebCore::WebGLRenderingContextBase::drawElements):
+        (WebCore::WebGLRenderingContextBase::enable):
+        (WebCore::WebGLRenderingContextBase::readPixels):
+        (WebCore::WebGLRenderingContextBase::copyTexImage2D):
+        (WebCore::WebGLRenderingContextBase::drawArraysInstanced):
+        (WebCore::WebGLRenderingContextBase::drawElementsInstanced):
+        * html/canvas/WebGLRenderingContextBase.h:
+
 2020-11-30  Simon Fraser  <[email protected]>
 
         Unreviewed build fix.

Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp (270252 => 270253)


--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp	2020-11-30 19:08:40 UTC (rev 270252)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp	2020-11-30 19:20:52 UTC (rev 270253)
@@ -1340,7 +1340,7 @@
         return;
     if (!validateTexture3DBinding("copyTexSubImage3D", target))
         return;
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
     m_context->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
 }
 
@@ -3566,7 +3566,7 @@
     // taint the origin using the WebGL API.
     ASSERT(canvasBase().originClean());
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
 
     GCGLsizei length, columns, rows;
     m_context->getExtensions().readnPixelsRobustANGLE(x, y, width, height, format, type, 0, &length, &columns, &rows, reinterpret_cast<uint8_t*>(offset), true);

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (270252 => 270253)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-11-30 19:08:40 UTC (rev 270252)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-11-30 19:20:52 UTC (rev 270253)
@@ -461,6 +461,27 @@
     bool m_enabled;
 };
 
+class ScopedDisableRasterizerDiscard {
+public:
+    explicit ScopedDisableRasterizerDiscard(WebGLRenderingContextBase* context, bool wasEnabled)
+        : m_context(context)
+        , m_wasEnabled(wasEnabled)
+    {
+        if (m_wasEnabled)
+            m_context->disable(GraphicsContextGL::RASTERIZER_DISCARD);
+    }
+
+    ~ScopedDisableRasterizerDiscard()
+    {
+        if (m_wasEnabled)
+            m_context->enable(GraphicsContextGL::RASTERIZER_DISCARD);
+    }
+
+private:
+    WebGLRenderingContextBase* m_context;
+    bool m_wasEnabled;
+};
+
 #define ADD_VALUES_TO_SET(set, arr) \
     set.add(arr, arr + WTF_ARRAY_LENGTH(arr))
 
@@ -865,7 +886,9 @@
     m_stencilFuncMaskBack = 0xFFFFFFFF;
     m_layerCleared = false;
     m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
-    
+
+    m_rasterizerDiscardEnabled = false;
+
     m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
     m_scissorEnabled = false;
     m_clearDepth = 1;
@@ -1097,7 +1120,7 @@
     canvas->notifyObserversCanvasChanged(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
 }
 
-bool WebGLRenderingContextBase::clearIfComposited(GCGLbitfield mask)
+bool WebGLRenderingContextBase::clearIfComposited(WebGLRenderingContextBase::ClearCaller caller, GCGLbitfield mask)
 {
     if (isContextLostOrPending())
         return false;
@@ -1107,7 +1130,7 @@
 
     GCGLbitfield buffersNeedingClearing = m_context->getBuffersToAutoClear();
 
-    if (!buffersNeedingClearing || (mask && m_framebufferBinding))
+    if (!buffersNeedingClearing || (mask && m_framebufferBinding) || (m_rasterizerDiscardEnabled && caller == ClearCallerDrawOrClear))
         return false;
 
     // Use the underlying GraphicsContext3D's attributes to take into
@@ -1145,10 +1168,13 @@
     GCGLenum bindingPoint = isWebGL2() ? GraphicsContextGL::DRAW_FRAMEBUFFER : GraphicsContextGL::FRAMEBUFFER;
     if (m_framebufferBinding)
         m_context->bindFramebuffer(bindingPoint, 0);
-    // If the WebGL 2.0 clearBuffer APIs already have been used to
-    // selectively clear some of the buffers, don't destroy those
-    // results.
-    m_context->clear(clearMask & buffersNeedingClearing);
+    {
+        ScopedDisableRasterizerDiscard disable(this, m_rasterizerDiscardEnabled);
+        // If the WebGL 2.0 clearBuffer APIs already have been used to
+        // selectively clear some of the buffers, don't destroy those
+        // results.
+        m_context->clear(clearMask & buffersNeedingClearing);
+    }
     m_context->setBuffersToAutoClear(0);
 
     restoreStateAfterClear();
@@ -1200,7 +1226,7 @@
             canvas->clearPresentationCopy();
     }
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
 
     if (!m_markedCanvasDirty && !m_layerCleared)
         return;
@@ -1217,7 +1243,7 @@
 {
     if (isContextLostOrPending())
         return nullptr;
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
     return m_context->paintRenderingResultsToImageData();
 }
 
@@ -1680,7 +1706,7 @@
         return;
     }
 #endif
-    if (!clearIfComposited(mask))
+    if (!clearIfComposited(ClearCallerDrawOrClear, mask))
         m_context->clear(mask);
     markContextChangedAndNotifyCanvasObserver();
 }
@@ -1857,7 +1883,7 @@
 #if USE(ANGLE)
     if (!validateTexture2DBinding("copyTexSubImage2D", target))
         return;
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
     m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
 #else
     if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
@@ -1888,7 +1914,7 @@
         synthesizeGLError(GraphicsContextGL::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
         return;
     }
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
 
     GCGLint clippedX, clippedY;
     GCGLsizei clippedWidth, clippedHeight;
@@ -2169,6 +2195,8 @@
     }
     if (cap == GraphicsContextGL::SCISSOR_TEST)
         m_scissorEnabled = false;
+    if (cap == GraphicsContextGL::RASTERIZER_DISCARD)
+        m_rasterizerDiscardEnabled = false;
     m_context->disable(cap);
 }
 
@@ -2536,7 +2564,7 @@
     if (m_currentProgram && InspectorInstrumentation::isWebGLProgramDisabled(*this, *m_currentProgram))
         return;
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerDrawOrClear);
 
 #if !USE(ANGLE)
     bool vertexAttrib0Simulated = false;
@@ -2599,7 +2627,7 @@
     if (m_currentProgram && InspectorInstrumentation::isWebGLProgramDisabled(*this, *m_currentProgram))
         return;
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerDrawOrClear);
 
 #if !USE(ANGLE)
     bool vertexAttrib0Simulated = false;
@@ -2650,6 +2678,8 @@
     }
     if (cap == GraphicsContextGL::SCISSOR_TEST)
         m_scissorEnabled = true;
+    if (cap == GraphicsContextGL::RASTERIZER_DISCARD)
+        m_rasterizerDiscardEnabled = true;
     m_context->enable(cap);
 }
 
@@ -4334,7 +4364,7 @@
     }
 #endif // USE(ANGLE)
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
     void* data = ""
 
 #if USE(ANGLE)
@@ -5593,7 +5623,7 @@
     if (!tex)
         return;
 #if USE(ANGLE)
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
     m_context->copyTexImage2D(target, level, internalFormat, x, y, width, height, border);
 #else
     if (!isTexInternalFormatColorBufferCombinationValid(internalFormat, getBoundReadFramebufferColorFormat())) {
@@ -5609,7 +5639,7 @@
         synthesizeGLError(GraphicsContextGL::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
         return;
     }
-    clearIfComposited();
+    clearIfComposited(ClearCallerOther);
 
     GCGLint clippedX, clippedY;
     GCGLsizei clippedWidth, clippedHeight;
@@ -7685,7 +7715,7 @@
         return;
 #endif // !USE(ANGLE)
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerDrawOrClear);
 
 #if !USE(ANGLE)
     bool vertexAttrib0Simulated = false;
@@ -7731,7 +7761,7 @@
         return;
 #endif // !USE(ANGLE)
 
-    clearIfComposited();
+    clearIfComposited(ClearCallerDrawOrClear);
 
 #if !USE(ANGLE)
     bool vertexAttrib0Simulated = false;

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (270252 => 270253)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2020-11-30 19:08:40 UTC (rev 270252)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2020-11-30 19:20:52 UTC (rev 270253)
@@ -647,6 +647,8 @@
     GCGLint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
     GCGLuint m_stencilFuncMask, m_stencilFuncMaskBack;
 
+    bool m_rasterizerDiscardEnabled { false };
+
     bool m_isGLES2Compliant;
     bool m_isGLES2NPOTStrict;
     bool m_isDepthStencilSupported;
@@ -718,10 +720,17 @@
     RefPtr<Float32Array> getWebGLFloatArrayParameter(GCGLenum);
     RefPtr<Int32Array> getWebGLIntArrayParameter(GCGLenum);
 
+    enum ClearCaller {
+        // Caller of ClearIfComposited is a user-level draw or clear call.
+        ClearCallerDrawOrClear,
+        // Caller of ClearIfComposited is anything else, including
+        // readbacks or copies.
+        ClearCallerOther,
+    };
     // Clear the backbuffer if it was composited since the last operation.
     // clearMask is set to the bitfield of any clear that would happen anyway at this time
     // and the function returns true if that clear is now unnecessary.
-    bool clearIfComposited(GCGLbitfield clearMask = 0);
+    bool clearIfComposited(ClearCaller, GCGLbitfield clearMask = 0);
 
     // Helper to restore state that clearing the framebuffer may destroy.
     void restoreStateAfterClear();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to