Bug 1429994 - Use ID3D11Query to wait previous frame completion r=nical
☠☠ backed out by 29d6104e3166 ☠ ☠
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 19 Jan 2018 07:49:08 +0900
changeset 399910 70c2890fb8759067869e582c71d8123c9535841e
parent 399909 4b7ad48ad5e51a5614e764f20eabae8aa1c4d9e8
child 399911 29d6104e3166227e759797ef127b5ed60eedbe7d
push id99052
push usersikeda@mozilla.com
push dateThu, 18 Jan 2018 22:49:25 +0000
treeherdermozilla-inbound@70c2890fb875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1429994
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 1429994 - Use ID3D11Query to wait previous frame completion r=nical
gfx/webrender_bindings/RenderCompositor.cpp
gfx/webrender_bindings/RenderCompositorANGLE.cpp
gfx/webrender_bindings/RenderCompositorANGLE.h
gfx/webrender_bindings/RenderCompositorOGL.cpp
gfx/webrender_bindings/RenderCompositorOGL.h
gfx/webrender_bindings/moz.build
--- a/gfx/webrender_bindings/RenderCompositor.cpp
+++ b/gfx/webrender_bindings/RenderCompositor.cpp
@@ -2,26 +2,36 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RenderCompositor.h"
 
 #include "GLContext.h"
+#include "mozilla/gfx/gfxVars.h"
 #include "mozilla/layers/SyncObject.h"
 #include "mozilla/webrender/RenderCompositorOGL.h"
 #include "mozilla/widget/CompositorWidget.h"
 
+#ifdef XP_WIN
+#include "mozilla/webrender/RenderCompositorANGLE.h"
+#endif
+
 namespace mozilla {
 namespace wr {
 
 /* static */ UniquePtr<RenderCompositor>
 RenderCompositor::Create(RefPtr<widget::CompositorWidget>&& aWidget)
 {
+#ifdef XP_WIN
+  if (gfx::gfxVars::UseWebRenderANGLE()) {
+    return RenderCompositorANGLE::Create(Move(aWidget));
+  }
+#endif
   return RenderCompositorOGL::Create(Move(aWidget));
 }
 
 RenderCompositor::RenderCompositor(RefPtr<widget::CompositorWidget>&& aWidget)
   : mWidget(aWidget)
 {
 }
 
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RenderCompositorANGLE.h"
+
+#include "GLContext.h"
+#include "GLContextEGL.h"
+#include "GLContextProvider.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/layers/HelpersD3D11.h"
+#include "mozilla/layers/SyncObject.h"
+#include "mozilla/widget/CompositorWidget.h"
+
+#include <d3d11.h>
+
+namespace mozilla {
+namespace wr {
+
+/* static */ UniquePtr<RenderCompositor>
+RenderCompositorANGLE::Create(RefPtr<widget::CompositorWidget>&& aWidget)
+{
+  UniquePtr<RenderCompositorANGLE> compositor = MakeUnique<RenderCompositorANGLE>(Move(aWidget));
+  if (!compositor->Initialize()) {
+    return nullptr;
+  }
+  return compositor;
+}
+
+RenderCompositorANGLE::RenderCompositorANGLE(RefPtr<widget::CompositorWidget>&& aWidget)
+  : RenderCompositor(Move(aWidget))
+{
+}
+
+RenderCompositorANGLE::~RenderCompositorANGLE()
+{
+}
+
+bool
+RenderCompositorANGLE::Initialize()
+{
+  mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice();
+  if (!mDevice) {
+    gfxCriticalNote << "[D3D11] failed to get compositor device.";
+    return false;
+  }
+
+  mDevice->GetImmediateContext(getter_AddRefs(mCtx));
+  if (!mCtx) {
+    gfxCriticalNote << "[D3D11] failed to get immediate context.";
+    return false;
+  }
+
+  mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(mDevice);
+  if (!mSyncObject->Init()) {
+    // Some errors occur. Clear the mSyncObject here.
+    // Then, there will be no texture synchronization.
+    return false;
+  }
+
+  mGL = gl::GLContextProviderEGL::CreateForCompositorWidget(mWidget, true);
+  if (!mGL || !mGL->IsANGLE()) {
+    gfxCriticalNote << "Failed ANGLE GL context creation for WebRender: " << gfx::hexa(mGL.get());
+    return false;
+  }
+  if (!mGL->MakeCurrent()) {
+    gfxCriticalNote << "Failed GL context creation for WebRender: " << gfx::hexa(mGL.get());
+    return false;
+  }
+
+  return true;
+}
+
+bool
+RenderCompositorANGLE::Destroy()
+{
+  return true;
+}
+
+bool
+RenderCompositorANGLE::BeginFrame()
+{
+  if (!mGL->MakeCurrent()) {
+    gfxCriticalNote << "Failed to make render context current, can't draw.";
+    return false;
+  }
+
+  if (mSyncObject) {
+    // XXX: if the synchronization is failed, we should handle the device reset.
+    mSyncObject->Synchronize();
+  }
+  return true;
+}
+
+void
+RenderCompositorANGLE::EndFrame()
+{
+  InsertPresentWaitQuery();
+
+  mGL->SwapBuffers();
+
+  // 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.
+  //   Insert query #3
+  //   Present #3
+  //   Wait for query #2.
+  //
+  // This ensures we're done reading textures before swapping buffers.
+  WaitForPreviousPresentQuery();
+}
+
+void
+RenderCompositorANGLE::Pause()
+{
+}
+
+bool
+RenderCompositorANGLE::Resume()
+{
+  return true;
+}
+
+LayoutDeviceIntSize
+RenderCompositorANGLE::GetClientSize()
+{
+  return mWidget->GetClientSize();
+}
+
+void
+RenderCompositorANGLE::InsertPresentWaitQuery()
+{
+  CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
+  HRESULT hr = mDevice->CreateQuery(&desc, getter_AddRefs(mNextWaitForPresentQuery));
+  if (FAILED(hr) || !mNextWaitForPresentQuery) {
+    gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << hexa(hr);
+    return;
+  }
+
+  mCtx->End(mNextWaitForPresentQuery);
+}
+
+void
+RenderCompositorANGLE::WaitForPreviousPresentQuery()
+{
+  if (mWaitForPresentQuery) {
+    BOOL result;
+    layers::WaitForGPUQuery(mDevice, mCtx, mWaitForPresentQuery, &result);
+  }
+  mWaitForPresentQuery = mNextWaitForPresentQuery.forget();
+}
+
+
+} // namespace wr
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_RENDERCOMPOSITOR_ANGLE_H
+#define MOZILLA_GFX_RENDERCOMPOSITOR_ANGLE_H
+
+#include "mozilla/webrender/RenderCompositor.h"
+
+struct ID3D11DeviceContext;
+struct ID3D11Device;
+struct ID3D11Query;
+
+namespace mozilla {
+
+namespace wr {
+
+class RenderCompositorANGLE : public RenderCompositor
+{
+public:
+  static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
+
+  RenderCompositorANGLE(RefPtr<widget::CompositorWidget>&& aWidget);
+  virtual ~RenderCompositorANGLE();
+  bool Initialize();
+
+  bool Destroy() override;
+  bool BeginFrame() override;
+  void EndFrame() override;
+  void Pause() override;
+  bool Resume() override;
+
+  gl::GLContext* gl() const override { return mGL; }
+
+  bool UseANGLE() const override { return true; }
+
+  LayoutDeviceIntSize GetClientSize() override;
+
+protected:
+  void InsertPresentWaitQuery();
+  void WaitForPreviousPresentQuery();
+
+  RefPtr<gl::GLContext> mGL;
+
+  RefPtr<ID3D11Device> mDevice;
+  RefPtr<ID3D11DeviceContext> mCtx;
+
+  RefPtr<ID3D11Query> mWaitForPresentQuery;
+  RefPtr<ID3D11Query> mNextWaitForPresentQuery;
+
+};
+
+} // namespace wr
+} // namespace mozilla
+
+#endif
--- a/gfx/webrender_bindings/RenderCompositorOGL.cpp
+++ b/gfx/webrender_bindings/RenderCompositorOGL.cpp
@@ -3,77 +3,39 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RenderCompositorOGL.h"
 
 #include "GLContext.h"
 #include "GLContextProvider.h"
-#include "mozilla/gfx/gfxVars.h"
-#include "mozilla/layers/SyncObject.h"
 #include "mozilla/widget/CompositorWidget.h"
 
-#ifdef XP_WIN
-#include "GLContextEGL.h"
-#endif
-
 namespace mozilla {
 namespace wr {
 
 /* static */ UniquePtr<RenderCompositor>
 RenderCompositorOGL::Create(RefPtr<widget::CompositorWidget>&& aWidget)
 {
   RefPtr<gl::GLContext> gl;
-  if (gfx::gfxVars::UseWebRenderANGLE()) {
-    gl = gl::GLContextProviderEGL::CreateForCompositorWidget(aWidget, true);
-    if (!gl || !gl->IsANGLE()) {
-      gfxCriticalNote << "Failed ANGLE GL context creation for WebRender: " << gfx::hexa(gl.get());
-      return nullptr;
-    }
-  }
-  if (!gl) {
-    gl = gl::GLContextProvider::CreateForCompositorWidget(aWidget, true);
-  }
+  gl = gl::GLContextProvider::CreateForCompositorWidget(aWidget, true);
   if (!gl || !gl->MakeCurrent()) {
     gfxCriticalNote << "Failed GL context creation for WebRender: " << gfx::hexa(gl.get());
     return nullptr;
   }
   return MakeUnique<RenderCompositorOGL>(Move(gl), Move(aWidget));
 }
 
 RenderCompositorOGL::RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
-                                             RefPtr<widget::CompositorWidget>&& aWidget)
+                                         RefPtr<widget::CompositorWidget>&& aWidget)
   : RenderCompositor(Move(aWidget))
   , mGL(aGL)
 {
   MOZ_ASSERT(mGL);
-
-#ifdef XP_WIN
-  if (mGL->IsANGLE()) {
-    gl::GLLibraryEGL* egl = &gl::sEGLLibrary;
-
-    // Fetch the D3D11 device.
-    EGLDeviceEXT eglDevice = nullptr;
-    egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
-    MOZ_ASSERT(eglDevice);
-    ID3D11Device* device = nullptr;
-    egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
-    MOZ_ASSERT(device);
-
-    mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(device);
-    if (mSyncObject) {
-      if (!mSyncObject->Init()) {
-        // Some errors occur. Clear the mSyncObject here.
-        // Then, there will be no texture synchronization.
-        mSyncObject = nullptr;
-      }
-    }
-  }
-#endif
 }
 
 RenderCompositorOGL::~RenderCompositorOGL()
 {
 }
 
 bool
 RenderCompositorOGL::Destroy()
@@ -83,21 +45,16 @@ RenderCompositorOGL::Destroy()
 
 bool
 RenderCompositorOGL::BeginFrame()
 {
   if (!mGL->MakeCurrent()) {
     gfxCriticalNote << "Failed to make render context current, can't draw.";
     return false;
   }
-
-  if (mSyncObject) {
-    // XXX: if the synchronization is failed, we should handle the device reset.
-    mSyncObject->Synchronize();
-  }
   return true;
 }
 
 void
 RenderCompositorOGL::EndFrame()
 {
   mGL->SwapBuffers();
 }
@@ -123,22 +80,16 @@ RenderCompositorOGL::Resume()
   }
   // RenewSurface internally calls MakeCurrent.
   return mGL->RenewSurface(mWidget);
 #else
   return true;
 #endif
 }
 
-bool
-RenderCompositorOGL::UseANGLE() const
-{
-  return mGL->IsANGLE();
-}
-
 LayoutDeviceIntSize
 RenderCompositorOGL::GetClientSize()
 {
   return mWidget->GetClientSize();
 }
 
 
 } // namespace wr
--- a/gfx/webrender_bindings/RenderCompositorOGL.h
+++ b/gfx/webrender_bindings/RenderCompositorOGL.h
@@ -5,29 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_RENDERCOMPOSITOR_OGL_H
 #define MOZILLA_GFX_RENDERCOMPOSITOR_OGL_H
 
 #include "mozilla/webrender/RenderCompositor.h"
 
 namespace mozilla {
-/*
-namespace gl {
-class GLContext;
-}
 
-namespace layers {
-class SyncObjectHost;
-}
-
-namespace widget {
-class CompositorWidget;
-}
-*/
 namespace wr {
 
 class RenderCompositorOGL : public RenderCompositor
 {
 public:
   static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
 
   RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
@@ -37,17 +25,17 @@ public:
   bool Destroy() override;
   bool BeginFrame() override;
   void EndFrame() override;
   void Pause() override;
   bool Resume() override;
 
   gl::GLContext* gl() const override { return mGL; }
 
-  bool UseANGLE() const override;
+  bool UseANGLE() const override { return false; }
 
   LayoutDeviceIntSize GetClientSize() override;
 
 protected:
   RefPtr<gl::GLContext> mGL;
 };
 
 } // namespace wr
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -42,19 +42,21 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
     ]
     UNIFIED_SOURCES += [
         'RenderMacIOSurfaceTextureHostOGL.cpp',
     ]
 
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
     EXPORTS.mozilla.webrender += [
+        'RenderCompositorANGLE.h',
         'RenderD3D11TextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
+        'RenderCompositorANGLE.cpp',
         'RenderD3D11TextureHostOGL.cpp',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')