Bug 1204922 - More information about crashes. r=bas a=ritu
authorMilan Sreckovic <milan@mozilla.com>
Tue, 27 Oct 2015 14:11:00 +0100
changeset 305563 74501e7db97fe014260a644554e05bd5d4061912
parent 305562 460116fc714afc60a5d05f95858d46fa6e849c23
child 305564 85d0f862ea1bdbfe69116cc683f6d6162bba782b
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas, ritu
bugs1204922
milestone44.0a2
Bug 1204922 - More information about crashes. r=bas a=ritu
gfx/2d/Logging.h
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -128,17 +128,18 @@ private:
 /// where such module would disable the output, in all but gfxDebug cases,
 /// we will still send a printf.
 
 // The range is due to the values set in Histograms.json
 enum class LogReason : int {
   MustBeMoreThanThis = -1,
   // Start.  Do not insert, always add at end.  If you remove items,
   // make sure the other items retain their values.
-
+  D3D11InvalidCallDeviceRemoved = 0,
+  D3D11InvalidCall = 1,
   // End
   MustBeLessThanThis = 101,
 };
 
 struct BasicLogger
 {
   // For efficiency, this method exists and copies the logic of the
   // OutputMessage below.  If making any changes here, also make it
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -475,16 +475,20 @@ CompositorD3D11::CreateRenderTarget(cons
 
   if (aRect.width * aRect.height == 0) {
     return nullptr;
   }
 
   CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1,
                              D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
 
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in CreateRenderTarget";
+  }
+
   RefPtr<ID3D11Texture2D> texture;
   HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
   if (Failed(hr) || !texture) {
     gfxCriticalNote << "Failed in CreateRenderTarget " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture, aRect.TopLeft());
@@ -508,16 +512,20 @@ CompositorD3D11::CreateRenderTargetFromS
   if (aRect.width * aRect.height == 0) {
     return nullptr;
   }
 
   CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
                              aRect.width, aRect.height, 1, 1,
                              D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
 
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in CreateRenderTargetFromSource";
+  }
+
   RefPtr<ID3D11Texture2D> texture;
   HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
   NS_ASSERTION(texture, "Could not create texture");
   if (Failed(hr) || !texture) {
     gfxCriticalNote << "Failed in CreateRenderTargetFromSource " << hexa(hr);
     return nullptr;
   }
 
@@ -1010,30 +1018,33 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
 void
 CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
                             const Rect* aClipRectIn,
                             const Rect& aRenderBounds,
                             Rect* aClipRectOut,
                             Rect* aRenderBoundsOut)
 {
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in BeginFrame";
+  }
+
   // Don't composite if we are minimised. Other than for the sake of efficency,
   // this is important because resizing our buffers when mimised will fail and
   // cause a crash when we're restored.
   NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?");
   if (::IsIconic(mHwnd) || mDevice->GetDeviceRemovedReason() != S_OK) {
     *aRenderBoundsOut = Rect();
     return;
   }
 
   IntSize oldSize = mSize;
-  UpdateRenderTarget();
 
   // Failed to create a render target or the view.
-  if (!mDefaultRT || !mDefaultRT->mRTView ||
+  if (!UpdateRenderTarget() || !mDefaultRT || !mDefaultRT->mRTView ||
       mSize.width <= 0 || mSize.height <= 0) {
     *aRenderBoundsOut = Rect();
     return;
   }
 
   mContext->IASetInputLayout(mAttachments->mInputLayout);
 
   ID3D11Buffer* buffer = mAttachments->mVertexBuffer;
@@ -1135,17 +1146,20 @@ CompositorD3D11::EndFrame()
         rects[i].bottom = r->YMost();
         rects[i].right = r->XMost();
         i++;
       }
 
       params.pDirtyRects = params.DirtyRectsCount ? rects.data() : nullptr;
       chain->Present1(presentInterval, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0, &params);
     } else {
-      mSwapChain->Present(presentInterval, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
+      hr = mSwapChain->Present(presentInterval, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
+      if (Failed(hr)) {
+        gfxCriticalNote << "D3D11 swap chain preset failed " << hexa(hr);
+      }
     }
     mDisableSequenceForNextFrame = false;
     if (mTarget) {
       PaintToTarget();
     }
   }
 
   mCurrentRT = nullptr;
@@ -1219,57 +1233,66 @@ CompositorD3D11::VerifyBufferSize()
     }
     MOZ_ASSERT(mDefaultRT->hasOneRef());
     mDefaultRT = nullptr;
   }
 
   hr = mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
                                  DXGI_FORMAT_B8G8R8A8_UNORM,
                                  0);
+  if (Failed(hr)) {
+    gfxCriticalNote << "D3D11 swap resize buffers failed " << hexa(hr) << " on " << mSize;
+  }
 
   return Succeeded(hr);
 }
 
-void
+bool
 CompositorD3D11::UpdateRenderTarget()
 {
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in UpdateRenderTarget";
+  }
+
   EnsureSize();
   if (!VerifyBufferSize()) {
     gfxCriticalNote << "Failed VerifyBufferSize in UpdateRenderTarget " << mSize;
-    return;
+    return false;
   }
 
   if (mDefaultRT) {
-    return;
+    return true;
   }
 
   if (mSize.width <= 0 || mSize.height <= 0) {
     gfxCriticalNote << "Invalid size in UpdateRenderTarget " << mSize;
-    return;
+    return false;
   }
 
   HRESULT hr;
 
   RefPtr<ID3D11Texture2D> backBuf;
 
   hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
   if (hr == DXGI_ERROR_INVALID_CALL) {
     // This happens on some GPUs/drivers when there's a TDR.
     if (mDevice->GetDeviceRemovedReason() != S_OK) {
       gfxCriticalError() << "GetBuffer returned invalid call!";
-      return;
+      return false;
     }
   }
   if (Failed(hr)) {
     gfxCriticalNote << "Failed in UpdateRenderTarget " << hexa(hr);
-    return;
+    return false;
   }
 
   mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0));
   mDefaultRT->SetSize(mSize);
+
+  return true;
 }
 
 bool
 DeviceAttachmentsD3D11::InitSyncObject()
 {
   // Sync object is not supported on WARP.
   if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
     return true;
@@ -1277,16 +1300,20 @@ DeviceAttachmentsD3D11::InitSyncObject()
 
   // It's okay to do this on Windows 8. But for now we'll just bail
   // whenever we're using WARP.
   CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
                              D3D11_BIND_SHADER_RESOURCE |
                              D3D11_BIND_RENDER_TARGET);
   desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
 
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in InitSyncObject";
+  }
+
   RefPtr<ID3D11Texture2D> texture;
   HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
   if (Failed(hr, "create sync texture")) {
     return false;
   }
 
   hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
   if (Failed(hr, "QI sync texture")) {
@@ -1405,16 +1432,20 @@ CompositorD3D11::PaintToTarget()
   CD3D11_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
   softDesc.MipLevels = 1;
   softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
   softDesc.Usage = D3D11_USAGE_STAGING;
   softDesc.BindFlags = 0;
 
   RefPtr<ID3D11Texture2D> readTexture;
 
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in PaintToTarget";
+  }
+
   hr = mDevice->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
   if (Failed(hr)) {
     gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false)) << "Failed in PaintToTarget 2";
     return;
   }
   mContext->CopyResource(readTexture, backBuf);
 
   D3D11_MAPPED_SUBRESOURCE map;
@@ -1452,32 +1483,42 @@ CompositorD3D11::HandleError(HRESULT hr,
   if (SUCCEEDED(hr)) {
     return;
   }
 
   if (aSeverity == Critical) {
     MOZ_CRASH("Unrecoverable D3D11 error");
   }
 
+  if (mDevice != gfxWindowsPlatform::GetPlatform()->GetD3D11Device()) {
+    gfxCriticalError() << "Out of sync D3D11 devices in HandleError";
+  }
+
+  HRESULT hrOnReset = S_OK;
   bool deviceRemoved = hr == DXGI_ERROR_DEVICE_REMOVED;
 
   if (deviceRemoved && mDevice) {
-    hr = mDevice->GetDeviceRemovedReason();
+    hrOnReset = mDevice->GetDeviceRemovedReason();
+  } else if (hr == DXGI_ERROR_INVALID_CALL && mDevice) {
+    hrOnReset = mDevice->GetDeviceRemovedReason();
+    if (hrOnReset != S_OK) {
+      deviceRemoved = true;
+    }
   }
 
   // Device reset may not be an error on our side, but can mess things up so
   // it's useful to see it in the reports.
   gfxCriticalError(CriticalLog::DefaultOptions(!deviceRemoved))
     << (deviceRemoved ? "[CompositorD3D11] device removed with error code: "
                       : "[CompositorD3D11] error code: ")
-    << hexa(hr);
+    << hexa(hr) << ", " << hexa(hrOnReset);
 
-  // Always crash if we are making invalid calls
+  // Crash if we are making invalid calls outside of device removal
   if (hr == DXGI_ERROR_INVALID_CALL) {
-    MOZ_CRASH("Invalid D3D11 api call");
+    gfxCrash(deviceRemoved ? LogReason::D3D11InvalidCallDeviceRemoved : LogReason::D3D11InvalidCall) << "Invalid D3D11 api call";
   }
 
   if (aSeverity == Recoverable) {
     NS_WARNING("Encountered a recoverable D3D11 error");
   }
 }
 
 bool
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -162,17 +162,17 @@ private:
 
   // Same as Failed(), except the severity is critical (with no abort) and
   // a string prefix must be provided.
   bool Failed(HRESULT hr, const char* aContext);
 
   // ensure mSize is up to date with respect to mWidget
   void EnsureSize();
   bool VerifyBufferSize();
-  void UpdateRenderTarget();
+  bool UpdateRenderTarget();
   bool UpdateConstantBuffers();
   void SetSamplerForFilter(gfx::Filter aFilter);
   void SetPSForEffect(Effect *aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat);
   void PaintToTarget();
 
   virtual gfx::IntSize GetWidgetSize() const override { return mSize; }
 
   RefPtr<ID3D11DeviceContext> mContext;