Bug 1325733 (flattened) - Mark read/draw calls better. - r=daoshengmu a=lizzard
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 23 Dec 2016 18:54:04 -0800
changeset 353260 45457cb05a323ad306920d9b9d95075c43c0d70f
parent 353259 927ea08a16a54e8c4322231249f9562e725465f5
child 353261 4df21f477536abb8f06a3000bd5d48ba50403ea4
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu, lizzard
bugs1325733
milestone52.0a2
Bug 1325733 (flattened) - Mark read/draw calls better. - r=daoshengmu a=lizzard Includes: * ANGLE needs to call clear twice even on larger targets. - r=daoshengmu
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLFramebuffer.cpp
dom/canvas/WebGLTextureUpload.cpp
gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
gfx/gl/GLContext.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -198,18 +198,16 @@ WebGLContext::WebGLContext()
         GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
         mMaxWarnings = 0;
     }
 
     mLastUseIndex = 0;
 
     InvalidateBufferFetching();
 
-    mBackbufferNeedsClear = true;
-
     mDisableFragHighP = false;
 
     mDrawCallsSinceLastFlush = 0;
 }
 
 WebGLContext::~WebGLContext()
 {
     RemovePostRefreshObserver();
@@ -1129,24 +1127,16 @@ WebGLContext::SetDimensions(int32_t sign
 }
 
 void
 WebGLContext::ClearBackbufferIfNeeded()
 {
     if (!mBackbufferNeedsClear)
         return;
 
-#ifdef DEBUG
-    gl->MakeCurrent();
-
-    GLuint fb = 0;
-    gl->GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &fb);
-    MOZ_ASSERT(fb == 0);
-#endif
-
     ClearScreen();
 
     mBackbufferNeedsClear = false;
 }
 
 void
 WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
 {
@@ -2088,16 +2078,26 @@ WebGLContext::ScopedDrawCallWrapper::~Sc
 /*static*/ bool
 WebGLContext::ScopedDrawCallWrapper::HasDepthButNoStencil(const WebGLFramebuffer* fb)
 {
     const auto& depth = fb->DepthAttachment();
     const auto& stencil = fb->StencilAttachment();
     return depth.IsDefined() && !stencil.IsDefined();
 }
 
+////
+
+void
+WebGLContext::OnBeforeReadCall()
+{
+    if (!mBoundReadFramebuffer) {
+        ClearBackbufferIfNeeded();
+    }
+}
+
 ////////////////////////////////////////
 
 IndexedBufferBinding::IndexedBufferBinding()
     : mRangeStart(0)
     , mRangeSize(0)
 { }
 
 uint64_t
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1977,21 +1977,24 @@ protected:
                 HasDepthButNoStencil(webgl.mBoundDrawFramebuffer))
             {
                 return true;
             }
 
             return false;
         }
 
+        ////
+
         explicit ScopedDrawCallWrapper(WebGLContext& webgl);
-
         ~ScopedDrawCallWrapper();
     };
 
+    void OnBeforeReadCall();
+
     void LoseOldestWebGLContextIfLimitExceeded();
     void UpdateLastUseIndex();
 
     template <typename WebGLObjectType>
     JS::Value WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType*,
                                    ErrorResult& rv) const;
     template <typename WebGLObjectType>
     JSObject* WebGLObjectAsJSObject(JSContext* cx, const WebGLObjectType*,
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1542,16 +1542,18 @@ WebGLContext::ReadPixelsImpl(GLint x, GL
     if (bytesNeeded > dataLen) {
         ErrorInvalidOperation("readPixels: buffer too small");
         return;
     }
 
     ////////////////
     // Now that the errors are out of the way, on to actually reading!
 
+    OnBeforeReadCall();
+
     uint32_t readX, readY;
     uint32_t writeX, writeY;
     uint32_t rwWidth, rwHeight;
     Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
     Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
 
     if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
         DoReadPixelsAndConvert(srcFormat->format, x, y, width, height, packFormat,
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -1857,16 +1857,17 @@ WebGLFramebuffer::BlitFramebuffer(WebGLC
     } else if (!srcFB && !dstFB) {
         webgl->ErrorInvalidOperation("%s: Feedback with default framebuffer.", funcName);
         return;
     }
 
     ////
 
     gl->MakeCurrent();
+    webgl->OnBeforeReadCall();
     WebGLContext::ScopedDrawCallWrapper wrapper(*webgl);
     gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
                          dstX0, dstY0, dstX1, dstY1,
                          mask, filter);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Goop.
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1977,18 +1977,17 @@ DoCopyTexOrSubImage(WebGLContext* webgl,
                     const WebGLTexture* tex, TexImageTarget target, GLint level,
                     GLint xWithinSrc, GLint yWithinSrc,
                     uint32_t srcTotalWidth, uint32_t srcTotalHeight,
                     const webgl::FormatUsageInfo* srcUsage,
                     GLint xOffset, GLint yOffset, GLint zOffset,
                     uint32_t dstWidth, uint32_t dstHeight,
                     const webgl::FormatUsageInfo* dstUsage)
 {
-    gl::GLContext* gl = webgl->gl;
-    gl->MakeCurrent();
+    const auto& gl = webgl->gl;
 
     ////
 
     uint32_t readX, readY;
     uint32_t writeX, writeY;
     uint32_t rwWidth, rwHeight;
     Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
     Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
@@ -2124,16 +2123,19 @@ WebGLTexture::CopyTexImage2D(TexImageTar
     }
 
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
+    mContext->gl->MakeCurrent();
+    mContext->OnBeforeReadCall();
+
     const bool isSubImage = false;
     if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
                              srcTotalWidth, srcTotalHeight, srcUsage, 0, 0, 0, width,
                              height, dstUsage))
     {
         return;
     }
 
@@ -2199,16 +2201,19 @@ WebGLTexture::CopyTexSubImage(const char
 
     auto srcFormat = srcUsage->format;
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
+    mContext->gl->MakeCurrent();
+    mContext->OnBeforeReadCall();
+
     bool uploadWillInitialize;
     if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
                                              yOffset, zOffset, width, height, depth,
                                              imageInfo, &uploadWillInitialize))
     {
         return;
     }
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
@@ -90,20 +90,19 @@ struct WorkaroundsD3D
     // vertex shaders. To work around this bug, we translate -(int) into ~(int)+1.
     bool rewriteUnaryMinusOperator = false;
 
     // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
     // this bug, we use an expression to emulate function isnan(). Tracking bug:
     // https://crbug.com/650547
     bool emulateIsnanFloat = false;
 
-    // On some Intel drivers, using clear() may not take effect. One of such situation is to clear
-    // a target with width or height < 16. To work around this bug, we call clear() twice on these
-    // platforms. Tracking bug: https://crbug.com/655534
-    bool callClearTwiceOnSmallTarget = false;
+    // On some Intel drivers, using clear() may not take effect. To work around this bug, we call
+    // clear() twice on these platforms. Tracking bug: https://crbug.com/655534
+    bool callClearTwice = false;
 
     // On some Intel drivers, copying from staging storage to constant buffer storage does not
     // seem to work. Work around this by keeping system memory storage as a canonical reference
     // for buffer data.
     // D3D11-only workaround. See http://crbug.com/593024.
     bool useSystemMemoryForConstantBuffers = false;
 };
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -366,33 +366,29 @@ gl::Error Clear11::clearFramebuffer(cons
 
                     D3D11_RECT rect;
                     rect.left   = clearParams.scissor.x;
                     rect.right  = clearParams.scissor.x + clearParams.scissor.width;
                     rect.top    = clearParams.scissor.y;
                     rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
 
                     deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
-                    if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
+
+                    if (mRenderer->getWorkarounds().callClearTwice)
                     {
-                        if (clearParams.scissor.width <= 16 || clearParams.scissor.height <= 16)
-                        {
-                            deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
-                        }
+                        deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
                     }
                 }
                 else
                 {
                     deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
-                    if (mRenderer->getWorkarounds().callClearTwiceOnSmallTarget)
+
+                    if (mRenderer->getWorkarounds().callClearTwice)
                     {
-                        if (framebufferSize.width <= 16 || framebufferSize.height <= 16)
-                        {
-                            deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
-                        }
+                        deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
                     }
                 }
             }
         }
     }
 
     if (clearParams.clearDepth || clearParams.clearStencil)
     {
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1852,17 +1852,17 @@ WorkaroundsD3D GenerateWorkarounds(const
 
     workarounds.preAddTexelFetchOffsets = IsIntel(adapterDesc.VendorId);
     workarounds.disableB5G6R5Support    = IsIntel(adapterDesc.VendorId);
     workarounds.rewriteUnaryMinusOperator =
         IsIntel(adapterDesc.VendorId) &&
         (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId));
     workarounds.emulateIsnanFloat =
         IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId);
-    workarounds.callClearTwiceOnSmallTarget =
+    workarounds.callClearTwice =
         IsIntel(adapterDesc.VendorId) && IsSkylake(adapterDesc.DeviceId);
 
     // TODO(jmadill): Disable when we have a fixed driver version.
     workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId);
 
     // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
     // depth stencil texture.  This is not allowed until feature level 10.1 but since it is not
     // possible to support ES3 on these devices, there is no need for the workaround to begin with
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -880,27 +880,31 @@ public:
         BEFORE_GL_CALL;
         mSymbols.fBindBuffer(target, buffer);
         AFTER_GL_CALL;
     }
 
     void fBindFramebuffer(GLenum target, GLuint framebuffer);
 
     void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
         mSymbols.fInvalidateFramebuffer(target, numAttachments, attachments);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
     void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
         mSymbols.fInvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
     void fBindTexture(GLenum target, GLuint texture) {
         BEFORE_GL_CALL;
         mSymbols.fBindTexture(target, texture);
         AFTER_GL_CALL;
     }
 
@@ -3133,21 +3137,23 @@ public:
                                 pixels);
         AFTER_GL_CALL;
     }
 
     void fCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset,
                             GLint yoffset, GLint zoffset, GLint x,
                             GLint y, GLsizei width, GLsizei height)
     {
+        BeforeGLReadCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fCopyTexSubImage3D);
         mSymbols.fCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset,
                                     x, y, width, height);
         AFTER_GL_CALL;
+        AfterGLReadCall();
     }
 
     void fCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
                                GLsizei width, GLsizei height, GLsizei depth,
                                GLint border, GLsizei imageSize, const GLvoid* data)
     {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fCompressedTexImage3D);