Bug 1425488 - Reset last fenceId on write to buffers. - r=lenzak
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 20 Dec 2017 16:31:58 -0800
changeset 448860 51feeb32d06dae76d62bfce41b58475cfde4282b
parent 448859 316f20b5e79bb9128fbf536ddb10dd4221083563
child 448861 26b8e4fcf9992db4e092312e28c26d2dac8d68e3
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslenzak
bugs1425488
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1425488 - Reset last fenceId on write to buffers. - r=lenzak MozReview-Commit-ID: HwPpGWKNA9W
dom/canvas/WebGL2ContextBuffers.cpp
dom/canvas/WebGLBuffer.cpp
dom/canvas/WebGLBuffer.h
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLContextGL.cpp
--- a/dom/canvas/WebGL2ContextBuffers.cpp
+++ b/dom/canvas/WebGL2ContextBuffers.cpp
@@ -81,16 +81,18 @@ WebGL2Context::CopyBufferSubData(GLenum 
                               (writeType == WebGLBuffer::Kind::OtherData) ? "other"
                                                                           : "element");
         return;
     }
 
     const ScopedLazyBind readBind(gl, readTarget, readBuffer);
     const ScopedLazyBind writeBind(gl, writeTarget, writeBuffer);
     gl->fCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
+
+    writeBuffer->ResetLastUpdateFenceId();
 }
 
 void
 WebGL2Context::GetBufferSubData(GLenum target, GLintptr srcByteOffset,
                                 const dom::ArrayBufferView& dstData, GLuint dstElemOffset,
                                 GLuint dstElemCountOverride)
 {
     const char funcName[] = "getBufferSubData";
@@ -127,26 +129,26 @@ WebGL2Context::GetBufferSubData(GLenum t
 
     ////
 
     switch (buffer->mUsage) {
     case LOCAL_GL_STATIC_READ:
     case LOCAL_GL_STREAM_READ:
     case LOCAL_GL_DYNAMIC_READ:
         if (mCompletedFenceId < buffer->mLastUpdateFenceId) {
-            GeneratePerfWarning("%s: Reading from a buffer without checking for previous"
-                                " command completion likely causes pipeline stalls."
-                                " Please use FenceSync.",
-                                funcName);
+            GenerateWarning("%s: Reading from a buffer without checking for previous"
+                            " command completion likely causes pipeline stalls."
+                            " Please use FenceSync.",
+                            funcName);
         }
         break;
     default:
-        GeneratePerfWarning("%s: Reading from a buffer with usage other than *_READ"
-                            " causes pipeline stalls. Copy through a STREAM_READ buffer.",
-                            funcName);
+        GenerateWarning("%s: Reading from a buffer with usage other than *_READ"
+                        " causes pipeline stalls. Copy through a STREAM_READ buffer.",
+                        funcName);
         break;
     }
 
     ////
 
     const ScopedLazyBind readBind(gl, target, buffer);
 
     if (byteLen) {
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -161,16 +161,18 @@ WebGLBuffer::BufferData(GLenum target, s
 
     if (mIndexCache) {
         if (!mIndexRanges.empty()) {
             mContext->GeneratePerfWarning("[%p] Invalidating %u ranges.", this,
                                           uint32_t(mIndexRanges.size()));
             mIndexRanges.clear();
         }
     }
+
+    ResetLastUpdateFenceId();
 }
 
 void
 WebGLBuffer::BufferSubData(GLenum target, size_t dstByteOffset, size_t dataLen,
                            const void* data) const
 {
     const char funcName[] = "bufferSubData";
 
@@ -192,16 +194,18 @@ WebGLBuffer::BufferSubData(GLenum target
     }
 
     ////
 
     const auto& gl = mContext->gl;
     const ScopedLazyBind lazyBind(gl, target, this);
 
     gl->fBufferSubData(target, dstByteOffset, dataLen, uploadData);
+
+    ResetLastUpdateFenceId();
 }
 
 bool
 WebGLBuffer::ValidateRange(const char* funcName, size_t byteOffset, size_t byteLen) const
 {
     auto availLength = mByteLength;
     if (byteOffset > availLength) {
         mContext->ErrorInvalidValue("%s: Offset passes the end of the buffer.", funcName);
@@ -404,16 +408,22 @@ WebGLBuffer::ValidateCanBindToTarget(con
 
     const auto dataType = (mContent == WebGLBuffer::Kind::OtherData) ? "other"
                                                                      : "element";
     mContext->ErrorInvalidOperation("%s: Buffer already contains %s data.", funcName,
                                     dataType);
     return false;
 }
 
+void
+WebGLBuffer::ResetLastUpdateFenceId() const
+{
+    mLastUpdateFenceId = mContext->mNextFenceId;
+}
+
 JSObject*
 WebGLBuffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLBufferBinding::Wrap(cx, this, givenProto);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLBuffer)
 
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -100,17 +100,17 @@ protected:
 
     void InvalidateCacheRange(uint64_t byteOffset, uint64_t byteLength) const;
 
     Kind mContent;
     GLenum mUsage;
     size_t mByteLength;
     size_t mTFBindCount;
     size_t mNonTFBindCount;
-    uint64_t mLastUpdateFenceId = 0;
+    mutable uint64_t mLastUpdateFenceId = 0;
 
     struct IndexRange final {
         GLenum type;
         uint64_t byteOffset;
         uint32_t indexCount;
 
         bool operator<(const IndexRange& x) const {
             if (type != x.type)
@@ -123,13 +123,15 @@ protected:
         }
     };
 
     UniqueBuffer mIndexCache;
     mutable std::map<IndexRange, Maybe<uint32_t>> mIndexRanges;
 
 public:
     CacheMapInvalidator mFetchInvalidator;
+
+    void ResetLastUpdateFenceId() const;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_BUFFER_H_
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -332,16 +332,20 @@ public:
                 if (buffer->IsBoundForNonTF()) {
                     mWebGL->ErrorInvalidOperation("%s: Transform feedback varying %u's"
                                                   " buffer is bound for"
                                                   " non-transform-feedback.",
                                                   funcName, i);
                     *out_error = true;
                     return;
                 }
+
+                // Technically we don't know that this will be updated yet, but we can
+                // speculatively mark it.
+                buffer->ResetLastUpdateFenceId();
             }
         }
 
         ////
 
         const auto& fetchLimits = linkInfo->GetDrawFetchLimits(funcName);
         if (!fetchLimits) {
             *out_error = true;
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1418,16 +1418,18 @@ WebGLContext::ReadPixels(GLint x, GLint 
     uint32_t bytesAfterOffset = 0;
     if (checkedBytesAfterOffset.isValid()) {
         bytesAfterOffset = checkedBytesAfterOffset.value();
     }
 
     const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, buffer);
 
     ReadPixelsImpl(x, y, width, height, format, type, (void*)offset, bytesAfterOffset);
+
+    buffer->ResetLastUpdateFenceId();
 }
 
 static webgl::PackingInfo
 DefaultReadPixelPI(const webgl::FormatUsageInfo* usage)
 {
     MOZ_ASSERT(usage->IsRenderable());
 
     switch (usage->format->componentType) {