Merge mozilla-inbound to mozilla-central a=merge
authorRazvan Maries <rmaries@mozilla.com>
Mon, 12 Nov 2018 11:58:52 +0200
changeset 502284 f97d54f24e02
parent 502278 9018814d9671 (current diff)
parent 502283 0b96f524756e (diff)
child 502296 a55ab1b0e478
child 502365 32fdd47e849a
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
first release with
nightly linux32
f97d54f24e02 / 65.0a1 / 20181112100105 / files
nightly linux64
f97d54f24e02 / 65.0a1 / 20181112100105 / files
nightly mac
f97d54f24e02 / 65.0a1 / 20181112100105 / files
nightly win32
f97d54f24e02 / 65.0a1 / 20181112100105 / files
nightly win64
f97d54f24e02 / 65.0a1 / 20181112100105 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central a=merge
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -539,17 +539,17 @@ AsyncImagePipelineManager::HoldExternalI
     SharedSurfacesParent::Release(aImageId);
     return;
   }
 
   holder->mExternalImages.push(ForwardingExternalImage(aEpoch, aImageId));
 }
 
 void
-AsyncImagePipelineManager::NotifyPipelinesUpdated(wr::WrPipelineInfo aInfo, bool aRender)
+AsyncImagePipelineManager::NotifyPipelinesUpdated(const wr::WrPipelineInfo& aInfo, bool aRender)
 {
   // This is called on the render thread, so we just stash the data into
   // UpdatesQueue and process it later on the compositor thread.
   MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
 
   // Increment the count when render happens.
   uint64_t currCount = aRender ? ++mUpdatesCount : mUpdatesCount;
   auto updates = MakeUnique<PipelineUpdates>(currCount, aRender);
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -51,17 +51,17 @@ public:
 
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture);
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHostWrapper* aWrTextureWrapper);
   void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, const wr::ExternalImageId& aImageId);
 
   // This is called from the Renderer thread to notify this class about the
   // pipelines in the most recently completed render. A copy of the update
   // information is put into mUpdatesQueue.
-  void NotifyPipelinesUpdated(wr::WrPipelineInfo aInfo, bool aRender);
+  void NotifyPipelinesUpdated(const wr::WrPipelineInfo& aInfo, bool aRender);
 
   // This is run on the compositor thread to process mUpdatesQueue. We make
   // this a public entry point because we need to invoke it from other places.
   void ProcessPipelineUpdates();
 
   TimeStamp GetCompositionTime() const {
     return mCompositionTime;
   }
--- a/gfx/webrender_bindings/RenderCompositor.h
+++ b/gfx/webrender_bindings/RenderCompositor.h
@@ -32,16 +32,17 @@ class RenderCompositor
 public:
   static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
 
   RenderCompositor(RefPtr<widget::CompositorWidget>&& aWidget);
   virtual ~RenderCompositor();
 
   virtual bool BeginFrame() = 0;
   virtual void EndFrame() = 0;
+  virtual void WaitForGPU() = 0;
   virtual void Pause() = 0;
   virtual bool Resume() = 0;
 
   virtual gl::GLContext* gl() const { return nullptr; }
 
   virtual bool MakeCurrent();
 
   virtual bool UseANGLE() const { return false; }
--- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp
@@ -336,17 +336,21 @@ RenderCompositorANGLE::EndFrame()
 {
   InsertPresentWaitQuery();
 
   mSwapChain->Present(0, 0);
 
   if (mCompositionDevice) {
     mCompositionDevice->Commit();
   }
+}
 
+void
+RenderCompositorANGLE::WaitForGPU()
+{
   // Note: this waits on the query we inserted in the previous frame,
   // not the one we just inserted now. Example:
   //   Insert query #1
   //   Present #1
   //   (first frame, no wait)
   //   Insert query #2
   //   Present #2
   //   Wait for query #1.
@@ -468,24 +472,41 @@ RenderCompositorANGLE::GetBufferSize()
 {
   MOZ_ASSERT(mBufferSize.isSome());
   if (mBufferSize.isNothing()) {
     return LayoutDeviceIntSize();
   }
   return mBufferSize.ref();
 }
 
+RefPtr<ID3D11Query>
+RenderCompositorANGLE::GetD3D11Query()
+{
+  RefPtr<ID3D11Query> query;
+
+  if (mRecycledQuery) {
+    query = mRecycledQuery.forget();
+    return query;
+  }
+
+  CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
+  HRESULT hr = mDevice->CreateQuery(&desc, getter_AddRefs(query));
+  if (FAILED(hr) || !query) {
+    gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << gfx::hexa(hr);
+    return nullptr;
+  }
+  return query;
+}
+
 void
 RenderCompositorANGLE::InsertPresentWaitQuery()
 {
   RefPtr<ID3D11Query> query;
-  CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
-  HRESULT hr = mDevice->CreateQuery(&desc, getter_AddRefs(query));
-  if (FAILED(hr) || !query) {
-    gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << gfx::hexa(hr);
+  query = GetD3D11Query();
+  if (!query) {
     return;
   }
 
   mCtx->End(query);
   mWaitForPresentQueries.emplace(query);
 }
 
 void
@@ -493,15 +514,17 @@ RenderCompositorANGLE::WaitForPreviousPr
 {
   size_t waitLatency = mUseTripleBuffering ? 3 : 2;
 
   while (mWaitForPresentQueries.size() >= waitLatency) {
     RefPtr<ID3D11Query>& query = mWaitForPresentQueries.front();
     BOOL result;
     layers::WaitForGPUQuery(mDevice, mCtx, query, &result);
 
+    // Recycle query for later use.
+    mRecycledQuery = query;
     mWaitForPresentQueries.pop();
   }
 }
 
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/RenderCompositorANGLE.h
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.h
@@ -33,16 +33,17 @@ public:
   static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
 
   explicit RenderCompositorANGLE(RefPtr<widget::CompositorWidget>&& aWidget);
   virtual ~RenderCompositorANGLE();
   bool Initialize();
 
   bool BeginFrame() override;
   void EndFrame() override;
+  void WaitForGPU() override;
   void Pause() override;
   bool Resume() override;
 
   gl::GLContext* gl() const override { return RenderThread::Get()->SharedGL(); }
 
   bool MakeCurrent() override;
 
   bool UseANGLE() const override { return true; }
@@ -56,31 +57,33 @@ public:
 protected:
   void InsertPresentWaitQuery();
   void WaitForPreviousPresentQuery();
   bool ResizeBufferIfNeeded();
   void DestroyEGLSurface();
   ID3D11Device* GetDeviceOfEGLDisplay();
   void CreateSwapChainForDCompIfPossible(IDXGIFactory2* aDXGIFactory2);
   bool SutdownEGLLibraryIfNecessary();
+  RefPtr<ID3D11Query> GetD3D11Query();
 
   EGLConfig mEGLConfig;
   EGLSurface mEGLSurface;
 
   int mUseTripleBuffering;
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11DeviceContext> mCtx;
   RefPtr<IDXGISwapChain> mSwapChain;
 
   RefPtr<IDCompositionDevice> mCompositionDevice;
   RefPtr<IDCompositionTarget> mCompositionTarget;
   RefPtr<IDCompositionVisual> mVisual;
 
   std::queue<RefPtr<ID3D11Query>> mWaitForPresentQueries;
+  RefPtr<ID3D11Query> mRecycledQuery;
 
   Maybe<LayoutDeviceIntSize> mBufferSize;
 };
 
 } // namespace wr
 } // namespace mozilla
 
 #endif
--- a/gfx/webrender_bindings/RenderCompositorOGL.cpp
+++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp
@@ -49,16 +49,21 @@ RenderCompositorOGL::BeginFrame()
 
 void
 RenderCompositorOGL::EndFrame()
 {
   mGL->SwapBuffers();
 }
 
 void
+RenderCompositorOGL::WaitForGPU()
+{
+}
+
+void
 RenderCompositorOGL::Pause()
 {
 #ifdef MOZ_WIDGET_ANDROID
   if (!mGL || mGL->IsDestroyed()) {
     return;
   }
   // ReleaseSurface internally calls MakeCurrent.
   mGL->ReleaseSurface();
--- a/gfx/webrender_bindings/RenderCompositorOGL.h
+++ b/gfx/webrender_bindings/RenderCompositorOGL.h
@@ -19,16 +19,17 @@ public:
   static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
 
   RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
                       RefPtr<widget::CompositorWidget>&& aWidget);
   virtual ~RenderCompositorOGL();
 
   bool BeginFrame() override;
   void EndFrame() override;
+  void WaitForGPU() override;
   void Pause() override;
   bool Resume() override;
 
   gl::GLContext* gl() const override { return mGL; }
 
   bool UseANGLE() const override { return false; }
 
   LayoutDeviceIntSize GetBufferSize() override;
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -335,37 +335,37 @@ RenderThread::RunEvent(wr::WindowId aWin
   }
 
   aEvent->Run(*this, aWindowId);
   aEvent = nullptr;
 }
 
 static void
 NotifyDidRender(layers::CompositorBridgeParent* aBridge,
-                wr::WrPipelineInfo aInfo,
+                RefPtr<WebRenderPipelineInfo> aInfo,
                 TimeStamp aStart,
                 TimeStamp aEnd,
                 bool aRender)
 {
   if (aRender && aBridge->GetWrBridge()) {
     // We call this here to mimic the behavior in LayerManagerComposite, as to
     // not change what Talos measures. That is, we do not record an empty frame
     // as a frame.
     aBridge->GetWrBridge()->RecordFrame();
   }
 
-  for (uintptr_t i = 0; i < aInfo.epochs.length; i++) {
+  auto info = aInfo->Raw();
+
+  for (uintptr_t i = 0; i < info.epochs.length; i++) {
     aBridge->NotifyPipelineRendered(
-        aInfo.epochs.data[i].pipeline_id,
-        aInfo.epochs.data[i].epoch,
+        info.epochs.data[i].pipeline_id,
+        info.epochs.data[i].epoch,
         aStart,
         aEnd);
   }
-
-  wr_pipeline_info_delete(aInfo);
 }
 
 void
 RenderThread::UpdateAndRender(wr::WindowId aWindowId,
                               const TimeStamp& aStartTime,
                               bool aRender,
                               const Maybe<gfx::IntSize>& aReadbackSize,
                               const Maybe<Range<uint8_t>>& aReadbackBuffer,
@@ -377,46 +377,55 @@ RenderThread::UpdateAndRender(wr::Window
 
   auto it = mRenderers.find(aWindowId);
   MOZ_ASSERT(it != mRenderers.end());
   if (it == mRenderers.end()) {
     return;
   }
 
   auto& renderer = it->second;
-
+  bool rendered = false;
   if (aRender) {
-    renderer->UpdateAndRender(aReadbackSize, aReadbackBuffer, aHadSlowFrame);
+    rendered = renderer->UpdateAndRender(aReadbackSize, aReadbackBuffer, aHadSlowFrame);
   } else {
     renderer->Update();
   }
   // Check graphics reset status even when rendering is skipped.
   renderer->CheckGraphicsResetStatus();
 
   TimeStamp end = TimeStamp::Now();
-
   auto info = renderer->FlushPipelineInfo();
-  RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
-      renderer->GetCompositorBridge()->GetAsyncImagePipelineManager();
-  // pipelineMgr should always be non-null here because it is only nulled out
-  // after the WebRenderAPI instance for the CompositorBridgeParent is
-  // destroyed, and that destruction blocks until the renderer thread has
-  // removed the relevant renderer. And after that happens we should never reach
-  // this code at all; it would bail out at the mRenderers.find check above.
-  MOZ_ASSERT(pipelineMgr);
-  pipelineMgr->NotifyPipelinesUpdated(info, aRender);
 
   layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction(
     "NotifyDidRenderRunnable",
     &NotifyDidRender,
     renderer->GetCompositorBridge(),
     info,
     aStartTime, end,
     aRender
   ));
+
+  if (rendered) {
+    // Wait for GPU after posting NotifyDidRender, since the wait is not
+    // necessary for the NotifyDidRender.
+    // The wait is necessary for Textures recycling of AsyncImagePipelineManager
+    // and for avoiding GPU queue is filled with too much tasks.
+    // WaitForGPU's implementation is different for each platform.
+    renderer->WaitForGPU();
+  }
+
+  RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
+      renderer->GetCompositorBridge()->GetAsyncImagePipelineManager();
+  // pipelineMgr should always be non-null here because it is only nulled out
+  // after the WebRenderAPI instance for the CompositorBridgeParent is
+  // destroyed, and that destruction blocks until the renderer thread has
+  // removed the relevant renderer. And after that happens we should never reach
+  // this code at all; it would bail out at the mRenderers.find check above.
+  MOZ_ASSERT(pipelineMgr);
+  pipelineMgr->NotifyPipelinesUpdated(info->Raw(), aRender);
 }
 
 void
 RenderThread::Pause(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   auto it = mRenderers.find(aWindowId);
@@ -790,16 +799,26 @@ WebRenderShaders::WebRenderShaders(gl::G
   mGL = gl;
   mShaders = wr_shaders_new(gl, programCache ? programCache->Raw() : nullptr);
 }
 
 WebRenderShaders::~WebRenderShaders() {
   wr_shaders_delete(mShaders, mGL.get());
 }
 
+WebRenderPipelineInfo::WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo)
+  : mPipelineInfo(aPipelineInfo)
+{
+}
+
+WebRenderPipelineInfo::~WebRenderPipelineInfo()
+{
+  wr_pipeline_info_delete(mPipelineInfo);
+}
+
 WebRenderThreadPool::WebRenderThreadPool()
 {
   mThreadPool = wr_thread_pool_new();
 }
 
 WebRenderThreadPool::~WebRenderThreadPool()
 {
   wr_thread_pool_delete(mThreadPool);
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -67,16 +67,29 @@ public:
 
   wr::WrShaders* RawShaders() { return mShaders; }
 
 protected:
   RefPtr<gl::GLContext> mGL;
   wr::WrShaders* mShaders;
 };
 
+class WebRenderPipelineInfo {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderPipelineInfo);
+public:
+  explicit WebRenderPipelineInfo(wr::WrPipelineInfo aPipelineInfo);
+
+  const wr::WrPipelineInfo& Raw() { return mPipelineInfo; }
+
+protected:
+  ~WebRenderPipelineInfo();
+
+  const wr::WrPipelineInfo mPipelineInfo;
+};
+
 /// Base class for an event that can be scheduled to run on the render thread.
 ///
 /// The event can be passed through the same channels as regular WebRender messages
 /// to preserve ordering.
 class RendererEvent
 {
 public:
   virtual ~RendererEvent() {}
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -190,16 +190,22 @@ RendererOGL::CheckGraphicsResetStatus()
         &DoNotifyWebRenderContextPurge,
         mBridge
       ));
     }
   }
 }
 
 void
+RendererOGL::WaitForGPU()
+{
+  mCompositor->WaitForGPU();
+}
+
+void
 RendererOGL::Pause()
 {
   mCompositor->Pause();
 }
 
 bool
 RendererOGL::Resume()
 {
@@ -224,20 +230,21 @@ RendererOGL::SetFrameStartTime(const Tim
   if (mFrameStartTime) {
     // frame start time is already set. This could happen when multiple
     // generate frame requests are merged by webrender.
     return;
   }
   mFrameStartTime = aTime;
 }
 
-wr::WrPipelineInfo
+RefPtr<WebRenderPipelineInfo>
 RendererOGL::FlushPipelineInfo()
 {
-  return wr_renderer_flush_pipeline_info(mRenderer);
+  auto info = wr_renderer_flush_pipeline_info(mRenderer);
+  return new WebRenderPipelineInfo(info);
 }
 
 RenderTextureHost*
 RendererOGL::GetRenderTexture(wr::WrExternalImageId aExternalImageId)
 {
   return mThread->GetRenderTexture(aExternalImageId);
 }
 
--- a/gfx/webrender_bindings/RendererOGL.h
+++ b/gfx/webrender_bindings/RendererOGL.h
@@ -55,17 +55,17 @@ public:
 
   /// This can be called on the render thread only.
   void Update();
 
   /// This can be called on the render thread only.
   bool UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize, const Maybe<Range<uint8_t>>& aReadbackBuffer, bool aHadSlowFrame);
 
   /// This can be called on the render thread only.
-  bool RenderToTarget(gfx::DrawTarget& aTarget);
+  void WaitForGPU();
 
   /// This can be called on the render thread only.
   void SetProfilerEnabled(bool aEnabled);
 
   /// This can be called on the render thread only.
   void SetFrameStartTime(const TimeStamp& aTime);
 
   /// This can be called on the render thread only.
@@ -86,17 +86,17 @@ public:
 
   /// This can be called on the render thread only.
   void CheckGraphicsResetStatus();
 
   layers::SyncObjectHost* GetSyncObject() const;
 
   layers::CompositorBridgeParent* GetCompositorBridge() { return mBridge; }
 
-  wr::WrPipelineInfo FlushPipelineInfo();
+  RefPtr<WebRenderPipelineInfo> FlushPipelineInfo();
 
   RenderTextureHost* GetRenderTexture(wr::WrExternalImageId aExternalImageId);
 
   wr::Renderer* GetRenderer() { return mRenderer; }
 
   gl::GLContext* gl() const;
 
 protected: