Bug 689870 - Add d3dkmtQueryStatistics.h and enable GPU reporter for Win7+. r=jrmuizel
authorHugh Nougher <hughnougher@gmail.com>
Thu, 02 May 2013 10:50:51 -0400
changeset 141578 f1fe50632492afca9fde019edb9f34ae5da5d735
parent 141577 5ac1564bff87ff999bb461ffebceb0a6308c95a2
child 141579 0727b84804805a770776a89f581ac12818c9124d
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs689870
milestone23.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 689870 - Add d3dkmtQueryStatistics.h and enable GPU reporter for Win7+. r=jrmuizel
gfx/thebes/d3dkmtQueryStatistics.h
gfx/thebes/gfxWindowsPlatform.cpp
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/d3dkmtQueryStatistics.h
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/. */
+/* This file is based on a header file that was briefly seen in the
+ * Windows 8 RC SDK. The work for this file itself was based on the one in ProcessHacker at
+ * http://processhacker.svn.sourceforge.net/viewvc/processhacker/2.x/trunk/plugins/ExtendedTools/d3dkmt.h?revision=4758&view=markup
+ * For more details see Mozilla Bug 689870.
+ */
+
+typedef struct _D3DKMTQS_COUNTER
+{
+    ULONG Count;
+    ULONGLONG Bytes;
+} D3DKMTQS_COUNTER;
+
+typedef struct _D3DKMTQS_ADAPTER_INFO
+{
+    ULONG NbSegments;
+
+    ULONG Filler[4];
+    ULONGLONG Filler2[2]; // Assumed sizeof(LONGLONG) = sizeof(ULONGLONG)
+    struct {
+        ULONG Filler[14];
+    } Filler_RDMAB;
+    struct {
+        ULONG Filler[9];
+    } Filler_R;
+    struct {
+        ULONG Filler[4];
+        D3DKMTQS_COUNTER Filler2;
+    } Filler_P;
+    struct {
+        D3DKMTQS_COUNTER Filler[16];
+        ULONG Filler2[2];
+    } Filler_PF;
+    struct {
+        ULONGLONG Filler[8];
+    } Filler_PT;
+    struct {
+        ULONG Filler[2];
+    } Filler_SR;
+    struct {
+        ULONG Filler[7];
+    } Filler_L;
+    struct {
+        D3DKMTQS_COUNTER Filler[7];
+    } Filler_A;
+    struct {
+        D3DKMTQS_COUNTER Filler[4];
+    } Filler_T;
+    ULONG64 Reserved[8];
+} D3DKMTQS_ADAPTER_INFO;
+
+typedef struct _D3DKMTQS_SEGMENT_INFO_WIN7
+{
+    ULONG Filler[3];
+    struct {
+        ULONGLONG Filler;
+        ULONG Filler2[2];
+    } Filler_M;
+
+    ULONG Aperture;
+
+    ULONGLONG Filler3[5];
+    ULONG64 Filler4[8];
+} D3DKMTQS_SEGMENT_INFO_WIN7;
+
+typedef struct _D3DKMTQS_SEGMENT_INFO_WIN8
+{
+    ULONGLONG Filler[3];
+    struct {
+        ULONGLONG Filler;
+        ULONG Filler2[2];
+    } Filler_M;
+
+    ULONG Aperture;
+
+    ULONGLONG Filler3[5];
+    ULONG64 Filler4[8];
+} D3DKMTQS_SEGMENT_INFO_WIN8;
+
+typedef struct _D3DKMTQS_SYSTEM_MEMORY
+{
+    ULONGLONG BytesAllocated;
+    ULONG Filler[2];
+    ULONGLONG Filler2[7];
+} D3DKMTQS_SYSTEM_MEMORY;
+
+typedef struct _D3DKMTQS_PROCESS_INFO
+{
+    ULONG Filler[2];
+    struct {
+        ULONGLONG BytesAllocated;
+
+        ULONG Filler[2];
+        ULONGLONG Filler2[7];
+    } SystemMemory;
+    ULONG64 Reserved[8];
+} D3DKMTQS_PROCESS_INFO;
+
+typedef struct _D3DKMTQS_PROCESS_SEGMENT_INFO
+{
+    ULONGLONG BytesCommitted;
+
+    ULONGLONG Filler[2];
+    ULONG Filler2;
+    struct {
+        ULONG Filler;
+        D3DKMTQS_COUNTER Filler2[6];
+        ULONGLONG Filler3;
+    } Filler3;
+    struct {
+        ULONGLONG Filler;
+    } Filler4;
+    ULONG64 Reserved[8];
+} D3DKMTQS_PROCESS_SEGMENT_INFO;
+
+typedef enum _D3DKMTQS_TYPE
+{
+    D3DKMTQS_ADAPTER = 0,
+    D3DKMTQS_PROCESS = 1,
+    D3DKMTQS_SEGMENT = 3,
+    D3DKMTQS_PROCESS_SEGMENT = 4,
+} D3DKMTQS_TYPE;
+
+typedef union _D3DKMTQS_RESULT
+{
+    D3DKMTQS_ADAPTER_INFO AdapterInfo;
+    D3DKMTQS_SEGMENT_INFO_WIN7 SegmentInfoWin7;
+    D3DKMTQS_SEGMENT_INFO_WIN8 SegmentInfoWin8;
+    D3DKMTQS_PROCESS_INFO ProcessInfo;
+    D3DKMTQS_PROCESS_SEGMENT_INFO ProcessSegmentInfo;
+} D3DKMTQS_RESULT;
+
+typedef struct _D3DKMTQS_QUERY_SEGMENT
+{
+    ULONG SegmentId;
+} D3DKMTQS_QUERY_SEGMENT;
+
+typedef struct _D3DKMTQS
+{
+    __in D3DKMTQS_TYPE Type;
+    __in LUID AdapterLuid;
+    __in_opt HANDLE hProcess;
+    __out D3DKMTQS_RESULT QueryResult;
+
+    union
+    {
+        __in D3DKMTQS_QUERY_SEGMENT QuerySegment;
+        __in D3DKMTQS_QUERY_SEGMENT QueryProcessSegment;
+    };
+} D3DKMTQS;
+
+extern "C" {
+typedef __checkReturn NTSTATUS (APIENTRY *PFND3DKMTQS)(__in const D3DKMTQS *);
+}
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -48,44 +48,19 @@ using namespace mozilla::gfx;
 
 #include <d3d10_1.h>
 
 #include "mozilla/gfx/2D.h"
 
 #include "nsMemory.h"
 #endif
 
-/*
- * Required headers are not available in the current consumer preview Win8
- * dev kit, disabling for now.
- */
-#undef MOZ_WINSDK_TARGETVER
-
-/**
- * XXX below should be >= MOZ_NTDDI_WIN8 or such which is not defined yet
- */
-#if MOZ_WINSDK_TARGETVER > MOZ_NTDDI_WIN7
-#define ENABLE_GPU_MEM_REPORTER
-#endif
-
-#if defined CAIRO_HAS_D2D_SURFACE || defined ENABLE_GPU_MEM_REPORTER
 #include "nsIMemoryReporter.h"
-#endif
-
-#ifdef ENABLE_GPU_MEM_REPORTER
 #include <winternl.h>
-
-/**
- * XXX need to check that extern C is really needed with Win8 SDK.
- *     It was required for files I had available at push time.
- */
-extern "C" {
-#include <d3dkmthk.h>
-}
-#endif
+#include "d3dkmtQueryStatistics.h"
 
 using namespace mozilla;
 
 #ifdef CAIRO_HAS_D2D_SURFACE
 
 static const char *kFeatureLevelPref =
   "gfx.direct3d.last_used_feature_level_idx";
 static const int kSupportedFeatureLevels[] =
@@ -185,17 +160,16 @@ typedef HRESULT (WINAPI*D3D10CreateDevic
 );
 
 typedef HRESULT(WINAPI*CreateDXGIFactory1Func)(
   REFIID riid,
   void **ppFactory
 );
 #endif
 
-#ifdef ENABLE_GPU_MEM_REPORTER
 class GPUAdapterMultiReporter : public nsIMemoryMultiReporter {
 
     // Callers must Release the DXGIAdapter after use or risk mem-leak
     static bool GetDXGIAdapter(__out IDXGIAdapter **DXGIAdapter)
     {
         ID3D10Device1 *D2D10Device;
         IDXGIDevice *DXGIDevice;
         bool result = false;
@@ -207,94 +181,102 @@ class GPUAdapterMultiReporter : public n
             }
         }
         
         return result;
     }
     
 public:
     NS_DECL_ISUPPORTS
+
+    // nsIMemoryMultiReporter abstract method implementation
+    NS_IMETHOD
+    GetName(nsACString &aName)
+    {
+        aName.AssignLiteral("gpuadapter");
+        return NS_OK;
+    }
     
     // nsIMemoryMultiReporter abstract method implementation
     NS_IMETHOD
     CollectReports(nsIMemoryMultiReporterCallback* aCb,
                    nsISupports* aClosure)
     {
         int32_t winVers, buildNum;
         HANDLE ProcessHandle = GetCurrentProcess();
         
         int64_t dedicatedBytesUsed = 0;
         int64_t sharedBytesUsed = 0;
         int64_t committedBytesUsed = 0;
         IDXGIAdapter *DXGIAdapter;
         
         HMODULE gdi32Handle;
-        PFND3DKMT_QUERYSTATISTICS queryD3DKMTStatistics;
+        PFND3DKMTQS queryD3DKMTStatistics;
         
         winVers = gfxWindowsPlatform::WindowsOSVersion(&buildNum);
         
         // GPU memory reporting is not available before Windows 7
         if (winVers < gfxWindowsPlatform::kWindows7) 
             return NS_OK;
         
         if (gdi32Handle = LoadLibrary(TEXT("gdi32.dll")))
-            queryD3DKMTStatistics = (PFND3DKMT_QUERYSTATISTICS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics");
+            queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics");
         
         if (queryD3DKMTStatistics && GetDXGIAdapter(&DXGIAdapter)) {
             // Most of this block is understood thanks to wj32's work on Process Hacker
             
             DXGI_ADAPTER_DESC adapterDesc;
-            D3DKMT_QUERYSTATISTICS queryStatistics;
+            D3DKMTQS queryStatistics;
             
             DXGIAdapter->GetDesc(&adapterDesc);
             DXGIAdapter->Release();
             
-            memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));
-            queryStatistics.Type = D3DKMT_QUERYSTATISTICS_PROCESS;
+            memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+            queryStatistics.Type = D3DKMTQS_PROCESS;
             queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
             queryStatistics.hProcess = ProcessHandle;
             if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
-                committedBytesUsed = queryStatistics.QueryResult.ProcessInformation.SystemMemory.BytesAllocated;
+                committedBytesUsed = queryStatistics.QueryResult.ProcessInfo.SystemMemory.BytesAllocated;
             }
             
-            memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));
-            queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER;
+            memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+            queryStatistics.Type = D3DKMTQS_ADAPTER;
             queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
             if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
                 ULONG i;
-                ULONG segmentCount = queryStatistics.QueryResult.AdapterInformation.NbSegments;
+                ULONG segmentCount = queryStatistics.QueryResult.AdapterInfo.NbSegments;
                 
                 for (i = 0; i < segmentCount; i++) {
-                    memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));
-                    queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT;
+                    memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+                    queryStatistics.Type = D3DKMTQS_SEGMENT;
                     queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
                     queryStatistics.QuerySegment.SegmentId = i;
                     
                     if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
                         bool aperture;
                         
                         // SegmentInformation has a different definition in Win7 than later versions
-                        if (winVers > gfxWindowsPlatform::kWindows7)
-                            aperture = queryStatistics.QueryResult.SegmentInformation.Aperture;
+                        if (winVers < gfxWindowsPlatform::kWindows8)
+                            aperture = queryStatistics.QueryResult.SegmentInfoWin7.Aperture;
                         else
-                            aperture = queryStatistics.QueryResult.SegmentInformationV1.Aperture;
+                            aperture = queryStatistics.QueryResult.SegmentInfoWin8.Aperture;
                         
-                        memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));
-                        queryStatistics.Type = D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT;
+                        memset(&queryStatistics, 0, sizeof(D3DKMTQS));
+                        queryStatistics.Type = D3DKMTQS_PROCESS_SEGMENT;
                         queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
                         queryStatistics.hProcess = ProcessHandle;
                         queryStatistics.QueryProcessSegment.SegmentId = i;
                         if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
                             if (aperture)
                                 sharedBytesUsed += queryStatistics.QueryResult
-                                                                  .ProcessSegmentInformation
+                                                                  .ProcessSegmentInfo
                                                                   .BytesCommitted;
                             else
                                 dedicatedBytesUsed += queryStatistics.QueryResult
-                                                                     .ProcessSegmentInformation
+                                                                     .ProcessSegmentInfo
                                                                      .BytesCommitted;
                         }
                     }
                 }
             }
         }
         
         FreeLibrary(gdi32Handle);
@@ -320,17 +302,16 @@ public:
                "In-process memory that is shared with the GPU.");
         
 #undef REPORT
 
         return NS_OK;
     }
 };
 NS_IMPL_ISUPPORTS1(GPUAdapterMultiReporter, nsIMemoryMultiReporter)
-#endif // ENABLE_GPU_MEM_REPORTER
 
 static __inline void
 BuildKeyNameFromFontName(nsAString &aName)
 {
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
     ToLowerCase(aName);
 }
@@ -356,27 +337,23 @@ gfxWindowsPlatform::gfxWindowsPlatform()
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVram));
     mD2DDevice = nullptr;
 #endif
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMDT));
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMSS));
 
     UpdateRenderMode();
 
-#ifdef ENABLE_GPU_MEM_REPORTER
     mGPUAdapterMultiReporter = new GPUAdapterMultiReporter();
     NS_RegisterMemoryMultiReporter(mGPUAdapterMultiReporter);
-#endif
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
-#ifdef ENABLE_GPU_MEM_REPORTER
     NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter);
-#endif
     
     ::ReleaseDC(NULL, mScreenDC);
     // not calling FT_Done_FreeType because cairo may still hold references to
     // these FT_Faces.  See bug 458169.
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mD2DDevice) {
         cairo_release_device(mD2DDevice);
     }