Bug 1124847. Track D3D11 shared texture usage in about:memory. r=bas
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Tue, 27 Jan 2015 20:09:34 -0500
changeset 226454 66f0f0b2bfd26dc1b5b3b6e5652de923632b8b1b
parent 226453 fe0c7de37b3234e1a39ab68ce2ed871b23330ea0
child 226455 00630c05fe80f5c199b987cd6f06edfd9a2c6f01
push id28196
push usercbook@mozilla.com
push dateThu, 29 Jan 2015 14:04:15 +0000
treeherdermozilla-central@a98d16e6a3b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1124847
milestone38.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 1124847. Track D3D11 shared texture usage in about:memory. r=bas This will hopefully help us track down large amounts of write-combined mappings that we see. try: -b do -p win32,win64 -u all -t none
gfx/layers/d3d11/TextureD3D11.cpp
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -359,16 +359,64 @@ TextureClientD3D11::BorrowDrawTarget()
     mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture10, mFormat);
   }
   if (!mDrawTarget) {
       gfxWarning() << "Invalid draw target for borrowing";
   }
   return mDrawTarget;
 }
 
+static const GUID sD3D11TextureUsage =
+{ 0xd89275b0, 0x6c7d, 0x4038, { 0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e } };
+
+/* This class get's it's lifetime tied to a D3D texture
+ * and increments memory usage on construction and decrements
+ * on destruction */
+class TextureMemoryMeasurer : public IUnknown
+{
+public:
+  TextureMemoryMeasurer(size_t aMemoryUsed)
+  {
+    mMemoryUsed = aMemoryUsed;
+    gfxWindowsPlatform::sD3D11MemoryUsed += mMemoryUsed;
+    mRefCnt = 0;
+  }
+  STDMETHODIMP_(ULONG) AddRef() {
+    mRefCnt++;
+    return mRefCnt;
+  }
+  STDMETHODIMP QueryInterface(REFIID riid,
+                              void **ppvObject)
+  {
+    IUnknown *punk = nullptr;
+    if (riid == IID_IUnknown) {
+      punk = this;
+    }
+    *ppvObject = punk;
+    if (punk) {
+      punk->AddRef();
+      return S_OK;
+    } else {
+      return E_NOINTERFACE;
+    }
+  }
+
+  STDMETHODIMP_(ULONG) Release() {
+    int refCnt = --mRefCnt;
+    if (refCnt == 0) {
+      gfxWindowsPlatform::sD3D11MemoryUsed -= mMemoryUsed;
+      delete this;
+    }
+    return refCnt;
+  }
+private:
+  int mRefCnt;
+  int mMemoryUsed;
+};
+
 bool
 TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
 {
   mSize = aSize;
   HRESULT hr;
 
   if (mFormat == SurfaceFormat::A8) {
     // Currently TextureClientD3D11 does not support A8 surfaces. Fallback.
@@ -381,32 +429,44 @@ TextureClientD3D11::AllocateForSurface(g
 
     CD3D11_TEXTURE2D_DESC newDesc(mFormat == SurfaceFormat::A8 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM,
                                   aSize.width, aSize.height, 1, 1,
                                   D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
 
     newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
 
     hr = d3d11device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));
+    if (FAILED(hr)) {
+      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
+      return false;
+    }
+    mTexture->SetPrivateDataInterface(sD3D11TextureUsage,
+                                      new TextureMemoryMeasurer(newDesc.Width * newDesc.Height *
+                                                                (mFormat == SurfaceFormat::A8 ?
+                                                                 1 : 4)));
   } else
   {
     ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
 
     CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
       aSize.width, aSize.height, 1, 1,
       D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
 
     newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
 
     hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture10));
-  }
+    if (FAILED(hr)) {
+      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D3D10] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
+      return false;
+    }
+    mTexture10->SetPrivateDataInterface(sD3D11TextureUsage,
+                                        new TextureMemoryMeasurer(newDesc.Width * newDesc.Height *
+                                                                  (mFormat == SurfaceFormat::A8 ?
+                                                                   1 : 4)));
 
-  if (FAILED(hr)) {
-    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
-    return false;
   }
 
   // Defer clearing to the next time we lock to avoid an extra (expensive) lock.
   mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
   mNeedsClearWhite = aFlags & ALLOC_CLEAR_BUFFER_WHITE;
 
   return true;
 }
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -320,16 +320,35 @@ public:
 #undef REPORT
 
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter)
 
+
+Atomic<size_t> gfxWindowsPlatform::sD3D11MemoryUsed;
+
+class D3D11TextureReporter MOZ_FINAL : public nsIMemoryReporter
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD CollectReports(nsIHandleReportCallback *aHandleReport,
+                            nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE
+  {
+      return MOZ_COLLECT_REPORT("d3d11-shared-textures", KIND_OTHER, UNITS_BYTES,
+                                gfxWindowsPlatform::sD3D11MemoryUsed,
+                                "Memory used for D3D11 shared textures");
+  }
+};
+
+NS_IMPL_ISUPPORTS(D3D11TextureReporter, nsIMemoryReporter)
+
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mD3D11DeviceInitialized(false)
   , mIsWARP(false)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     mUsingGDIFonts = false;
@@ -347,16 +366,17 @@ gfxWindowsPlatform::gfxWindowsPlatform()
 
     if (gfxPrefs::Direct2DUse1_1()) {
       InitD3D11Devices();
     }
 
     UpdateRenderMode();
 
     RegisterStrongMemoryReporter(new GPUAdapterReporter());
+    RegisterStrongMemoryReporter(new D3D11TextureReporter());
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
     mDeviceManager = nullptr;
 
     // not calling FT_Done_FreeType because cairo may still hold references to
     // these FT_Faces.  See bug 458169.
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -17,16 +17,17 @@
 #include "gfxWindowsSurface.h"
 #include "gfxFont.h"
 #ifdef CAIRO_HAS_DWRITE_FONT
 #include "gfxDWriteFonts.h"
 #endif
 #include "gfxPlatform.h"
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Atomics.h"
 #include "nsTArray.h"
 #include "nsDataHashtable.h"
 
 #include "mozilla/RefPtr.h"
 
 #include <windows.h>
 #include <objbase.h>
 
@@ -247,16 +248,18 @@ public:
     ID3D11Device *GetD3D11ContentDevice();
 
     mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
 
     static bool IsOptimus();
 
     bool IsWARP() { return mIsWARP; }
 
+    static mozilla::Atomic<size_t> sD3D11MemoryUsed;
+
 protected:
     RenderMode mRenderMode;
 
     int8_t mUseClearTypeForDownloadableFonts;
     int8_t mUseClearTypeAlways;
 
 private:
     void Init();