Bug 1409176 - make SyncObjectD3D11Client become fallible. r=dvander
authorJerryShih <hshih@mozilla.com>
Mon, 06 Nov 2017 16:07:22 +0800
changeset 443524 00b5d1cc54d3f45a0c2064b7530f131b9ad9c919
parent 443523 7bd9208b8c7c92521abfc8e4cae34bfbf419547a
child 443525 382939cc1ff5dc276d7c7d70d14fece9fbd59e77
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1409176
milestone58.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 1409176 - make SyncObjectD3D11Client become fallible. r=dvander Currently, the device-reset flow doesn't notify the decoder for device change immediately. The decoder might use an invalid sync-object for synchronization. Then, we will hit some assertions. This patch try to make the synchronization flow become fallible, then we could pass the error to the media framework for error handling. MozReview-Commit-ID: BFY32MmOdt0
gfx/layers/SyncObject.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
--- a/gfx/layers/SyncObject.h
+++ b/gfx/layers/SyncObject.h
@@ -23,49 +23,51 @@ typedef uintptr_t SyncHandle;
 class SyncObjectHost : public RefCounted<SyncObjectHost>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectHost)
   virtual ~SyncObjectHost() { }
 
   static already_AddRefed<SyncObjectHost> CreateSyncObjectHost(
 #ifdef XP_WIN
-                                                                       ID3D11Device* aDevice = nullptr
+                                                               ID3D11Device* aDevice = nullptr
 #endif
-                                                                      );
+                                                              );
 
   virtual bool Init() = 0;
 
   virtual SyncHandle GetSyncHandle() = 0;
 
+  // Return false for failed synchronization.
   virtual bool Synchronize() = 0;
 
 protected:
   SyncObjectHost() { }
 };
 
 class SyncObjectClient : public external::AtomicRefCounted<SyncObjectClient>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectClient)
   virtual ~SyncObjectClient() { }
 
   static already_AddRefed<SyncObjectClient> CreateSyncObjectClient(SyncHandle aHandle
 #ifdef XP_WIN
-                                                                     , ID3D11Device* aDevice = nullptr
+                                                                   , ID3D11Device* aDevice = nullptr
 #endif
-                                                                    );
+                                                                  );
 
   enum class SyncType {
     D3D11,
   };
 
   virtual SyncType GetSyncType() = 0;
 
-  virtual void Synchronize() = 0;
+  // Return false for failed synchronization.
+  virtual bool Synchronize(bool aFallible = false) = 0;
 
   virtual bool IsSyncObjectValid() = 0;
 
 protected:
   SyncObjectClient() { }
 };
 
 } // namespace layers
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -1692,40 +1692,45 @@ SyncObjectD3D11Client::SyncObjectD3D11Cl
     mDevice = DeviceManagerDx::Get()->GetContentDevice();
     return;
   }
 
   mDevice = aDevice;
 }
 
 bool
-SyncObjectD3D11Client::Init()
+SyncObjectD3D11Client::Init(bool aFallible)
 {
   if (mKeyedMutex) {
     return true;
   }
 
   HRESULT hr = mDevice->OpenSharedResource(
     mSyncHandle,
     __uuidof(ID3D11Texture2D),
     (void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
   if (FAILED(hr) || !mSyncTexture) {
     gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
-    if (ShouldDevCrashOnSyncInitFailure()) {
+    if (!aFallible && ShouldDevCrashOnSyncInitFailure()) {
       gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
     }
     return false;
   }
 
   hr = mSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
   if (FAILED(hr) || !mKeyedMutex) {
     // Leave both the critical error and MOZ_CRASH for now; the critical error lets
     // us "save" the hr value.  We will probably eventually replace this with gfxDevCrash.
-    gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
-    MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
+    if (!aFallible) {
+      gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
+      MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
+    } else {
+      gfxCriticalNote << "Failed to get KeyedMutex (3): " << hexa(hr);
+    }
+    return false;
   }
 
   return true;
 }
 
 void
 SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D* aTexture)
 {
@@ -1742,68 +1747,75 @@ SyncObjectD3D11Client::IsSyncObjectValid
   return true;
 }
 
 // We have only 1 sync object. As a thing that somehow works,
 // we copy each of the textures that need to be synced with the compositor
 // into our sync object and only use a lock for this sync object.
 // This way, we don't have to sync every texture we send to the compositor.
 // We only have to do this once per transaction.
-void
-SyncObjectD3D11Client::Synchronize()
+bool
+SyncObjectD3D11Client::Synchronize(bool aFallible)
 {
   // Since this can be called from either the Paint or Main thread.
   // We don't want this to race since we initialize the sync texture here
   // too.
   MutexAutoLock syncLock(mSyncLock);
 
   if (!mSyncedTextures.size()) {
-    return;
+    return true;
   }
-  if (!Init()) {
-    return;
+  if (!Init(aFallible)) {
+    return false;
   }
 
   HRESULT hr;
   AutoTextureLock lock(mKeyedMutex, hr, 20000);
 
   if (hr == WAIT_TIMEOUT) {
     if (DeviceManagerDx::Get()->HasDeviceReset()) {
       gfxWarning() << "AcquireSync timed out because of device reset.";
-      return;
+      return false;
     }
-    gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock";
+    if (aFallible) {
+      gfxWarning() << "Timeout on the D3D11 sync lock.";
+    } else {
+      gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock.";
+    }
+    return false;
   }
 
   D3D11_BOX box;
   box.front = box.top = box.left = 0;
   box.back = box.bottom = box.right = 1;
 
   RefPtr<ID3D11Device> dev;
   mSyncTexture->GetDevice(getter_AddRefs(dev));
 
   if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
     if (DeviceManagerDx::Get()->HasDeviceReset()) {
-      return;
+      return false;
     }
   }
 
   if (dev != mDevice) {
     gfxWarning() << "Attempt to sync texture from invalid device.";
-    return;
+    return false;
   }
 
   RefPtr<ID3D11DeviceContext> ctx;
   dev->GetImmediateContext(getter_AddRefs(ctx));
 
   for (auto iter = mSyncedTextures.begin(); iter != mSyncedTextures.end(); iter++) {
     ctx->CopySubresourceRegion(mSyncTexture, 0, 0, 0, 0, *iter, 0, &box);
   }
 
   mSyncedTextures.clear();
+
+  return true;
 }
 
 uint32_t
 GetMaxTextureSizeFromDevice(ID3D11Device* aDevice)
 {
   return GetMaxTextureSizeForFeatureLevel(aDevice->GetFeatureLevel());
 }
 
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -473,26 +473,26 @@ private:
   RefPtr<IDXGIKeyedMutex> mKeyedMutex;
 };
 
 class SyncObjectD3D11Client : public SyncObjectClient
 {
 public:
   explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice);
 
-  virtual void Synchronize() override;
+  virtual bool Synchronize(bool aFallible) override;
 
   virtual bool IsSyncObjectValid() override;
 
   virtual SyncType GetSyncType() override { return SyncType::D3D11; }
 
   void RegisterTexture(ID3D11Texture2D* aTexture);
 
 private:
-  bool Init();
+  bool Init(bool aFallible);
 
   SyncHandle mSyncHandle;
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11Texture2D> mSyncTexture;
   RefPtr<IDXGIKeyedMutex> mKeyedMutex;
   std::vector<ID3D11Texture2D*> mSyncedTextures;
   Mutex mSyncLock;
 };