Bug 1469480 - Fix simulate device reset handling r=nical
authorsotaro <sotaro.ikeda.g@gmail.com>
Tue, 19 Jun 2018 19:27:37 +0900
changeset 422968 e962019750e9396af45cb45b7b38fbf046d8c221
parent 422967 dfff9e92ca9710b2e56e0a38f86362b7a8903049
child 422969 84b05310b2c7a6b0c585add58fdb27e635e70963
push id34160
push userdluca@mozilla.com
push dateTue, 19 Jun 2018 21:55:15 +0000
treeherdermozilla-central@e429320fcdd2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1469480
milestone62.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 1469480 - Fix simulate device reset handling r=nical
gfx/ipc/GPUParent.cpp
gfx/webrender_bindings/RenderCompositorANGLE.cpp
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/RenderThread.h
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -379,16 +379,19 @@ GPUParent::RecvGetDeviceStatus(GPUDevice
 }
 
 mozilla::ipc::IPCResult
 GPUParent::RecvSimulateDeviceReset(GPUDeviceData* aOut)
 {
 #if defined(XP_WIN)
   DeviceManagerDx::Get()->ForceDeviceReset(ForcedDeviceResetReason::COMPOSITOR_UPDATED);
   DeviceManagerDx::Get()->MaybeResetAndReacquireDevices();
+  if (gfxVars::UseWebRender()) {
+    wr::RenderThread::Get()->SimulateDeviceReset();
+  }
 #endif
   RecvGetDeviceStatus(aOut);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 GPUParent::RecvNewContentCompositorManager(Endpoint<PCompositorManagerParent>&& aEndpoint)
 {
--- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp
+++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp
@@ -306,17 +306,17 @@ RenderCompositorANGLE::CreateSwapChainFo
     mCompositionDevice = dCompDevice;
   }
 }
 
 bool
 RenderCompositorANGLE::BeginFrame()
 {
   if (mDevice->GetDeviceRemovedReason() != S_OK) {
-    RenderThread::Get()->HandleDeviceReset("BeginFrame");
+    RenderThread::Get()->HandleDeviceReset("BeginFrame", /* aNotify */ true);
     return false;
   }
 
   mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
 
   if (!ResizeBufferIfNeeded()) {
     return false;
   }
@@ -324,17 +324,17 @@ RenderCompositorANGLE::BeginFrame()
   if (!mGL->MakeCurrent()) {
     gfxCriticalNote << "Failed to make render context current, can't draw.";
     return false;
   }
 
   if (mSyncObject) {
     if (!mSyncObject->Synchronize()) {
       // It's timeout or other error. Handle the device-reset here.
-      RenderThread::Get()->HandleDeviceReset("SyncObject");
+      RenderThread::Get()->HandleDeviceReset("SyncObject", /* aNotify */ true);
       return false;
     }
   }
   return true;
 }
 
 void
 RenderCompositorANGLE::EndFrame()
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -547,27 +547,29 @@ RenderThread::GetRenderTexture(wr::WrExt
 
 void
 RenderThread::ProgramCacheTask()
 {
   ProgramCache();
 }
 
 void
-RenderThread::HandleDeviceReset(const char* aWhere)
+RenderThread::HandleDeviceReset(const char* aWhere, bool aNotify)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   if (mHandlingDeviceReset) {
     return;
   }
 
-  gfxCriticalNote << "GFX: RenderThread detected a device reset in " << aWhere;
-  if (XRE_IsGPUProcess()) {
-    gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
+  if (aNotify) {
+    gfxCriticalNote << "GFX: RenderThread detected a device reset in " << aWhere;
+    if (XRE_IsGPUProcess()) {
+      gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
+    }
   }
 
   {
     MutexAutoLock lock(mRenderTextureMapLock);
     mRenderTexturesDeferred.clear();
     for (auto iter = mRenderTextures.Iter(); !iter.Done(); iter.Next()) {
       iter.UserData()->ClearCachedResources();
     }
@@ -579,16 +581,31 @@ RenderThread::HandleDeviceReset(const ch
 
 bool
 RenderThread::IsHandlingDeviceReset()
 {
   MOZ_ASSERT(IsInRenderThread());
   return mHandlingDeviceReset;
 }
 
+void
+RenderThread::SimulateDeviceReset()
+{
+  if (!IsInRenderThread()) {
+    Loop()->PostTask(NewRunnableMethod(
+      "RenderThread::SimulateDeviceReset",
+      this, &RenderThread::SimulateDeviceReset
+      ));
+  } else {
+    // When this function is called GPUProcessManager::SimulateDeviceReset() already
+    // triggers destroying all CompositorSessions before re-creating them.
+    HandleDeviceReset("SimulateDeviceReset", /* aNotify */ false);
+  }
+}
+
 WebRenderProgramCache*
 RenderThread::ProgramCache()
 {
   MOZ_ASSERT(IsInRenderThread());
 
   if (!mProgramCache) {
     mProgramCache = MakeUnique<WebRenderProgramCache>(ThreadPool().Raw());
   }
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -163,19 +163,21 @@ public:
 
   /// Can be called from any thread.
   WebRenderThreadPool& ThreadPool() { return mThreadPool; }
 
   /// Can only be called from the render thread.
   WebRenderProgramCache* ProgramCache();
 
   /// Can only be called from the render thread.
-  void HandleDeviceReset(const char* aWhere);
+  void HandleDeviceReset(const char* aWhere, bool aNotify);
   /// Can only be called from the render thread.
   bool IsHandlingDeviceReset();
+  /// Can be called from any thread.
+  void SimulateDeviceReset();
 
   size_t RendererCount();
 
 private:
   explicit RenderThread(base::Thread* aThread);
 
   void DeferredRenderTextureHostDestroy();
   void ShutDownTask(layers::SynchronousTask* aTask);