Browse Source

D3D11: Added GPU memory stats.

Branimir Karadžić 8 years ago
parent
commit
aa567d3d72

+ 10 - 7
include/bgfx/bgfx.h

@@ -741,14 +741,14 @@ namespace bgfx
 	///
 	struct Stats
 	{
-		uint64_t cpuTimeFrame;    //!< CPU time between two `bgfx::frame` calls.
-		uint64_t cpuTimeBegin;    //!< Render thread CPU submit begin time.
-		uint64_t cpuTimeEnd;      //!< Render thread CPU submit end time.
-		uint64_t cpuTimerFreq;    //!< CPU timer frequency.
+		int64_t cpuTimeFrame;    //!< CPU time between two `bgfx::frame` calls.
+		int64_t cpuTimeBegin;    //!< Render thread CPU submit begin time.
+		int64_t cpuTimeEnd;      //!< Render thread CPU submit end time.
+		int64_t cpuTimerFreq;    //!< CPU timer frequency.
 
-		uint64_t gpuTimeBegin;    //!< GPU frame begin time.
-		uint64_t gpuTimeEnd;      //!< GPU frame end time.
-		uint64_t gpuTimerFreq;    //!< GPU timer frequency.
+		int64_t gpuTimeBegin;    //!< GPU frame begin time.
+		int64_t gpuTimeEnd;      //!< GPU frame end time.
+		int64_t gpuTimerFreq;    //!< GPU timer frequency.
 
 		int64_t waitRender;       //!< Time spent waiting for render backend thread to finish issuing
 		                          //!  draw commands to underlying graphics API.
@@ -758,6 +758,9 @@ namespace bgfx
 		uint32_t numCompute;      //!< Number of compute calls submitted.
 		uint32_t maxGpuLatency;   //!< GPU driver latency.
 
+		int64_t gpuMemoryMax;     //!< Maximum available GPU memory.
+		int64_t gpuMemoryUsed;    //!< Available GPU memory.
+
 		uint16_t width;           //!< Backbuffer width in pixels.
 		uint16_t height;          //!< Backbuffer height in pixels.
 		uint16_t textWidth;       //!< Debug text width in characters.

+ 10 - 7
include/bgfx/c99/bgfx.h

@@ -348,14 +348,14 @@ typedef struct bgfx_view_stats
 /**/
 typedef struct bgfx_stats
 {
-    uint64_t cpuTimeFrame;
-    uint64_t cpuTimeBegin;
-    uint64_t cpuTimeEnd;
-    uint64_t cpuTimerFreq;
+    int64_t cpuTimeFrame;
+    int64_t cpuTimeBegin;
+    int64_t cpuTimeEnd;
+    int64_t cpuTimerFreq;
 
-    uint64_t gpuTimeBegin;
-    uint64_t gpuTimeEnd;
-    uint64_t gpuTimerFreq;
+    int64_t gpuTimeBegin;
+    int64_t gpuTimeEnd;
+    int64_t gpuTimerFreq;
 
     int64_t waitRender;
     int64_t waitSubmit;
@@ -364,6 +364,9 @@ typedef struct bgfx_stats
     uint32_t numCompute;
     uint32_t maxGpuLatency;
 
+    int64_t gpuMemoryMax;
+    int64_t gpuMemoryUsed;
+
     uint16_t width;
     uint16_t height;
     uint16_t textWidth;

+ 1 - 1
include/bgfx/defines.h

@@ -6,7 +6,7 @@
 #ifndef BGFX_DEFINES_H_HEADER_GUARD
 #define BGFX_DEFINES_H_HEADER_GUARD
 
-#define BGFX_API_VERSION UINT32_C(49)
+#define BGFX_API_VERSION UINT32_C(50)
 
 /// Color RGB/alpha/depth write. When it's not specified write will be disabled.
 #define BGFX_STATE_RGB_WRITE               UINT64_C(0x0000000000000001) //!< Enable RGB write.

+ 151 - 5
src/renderer_d3d11.cpp

@@ -562,8 +562,12 @@ namespace bgfx { namespace d3d11
 #endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT
 	}
 
-	// Reference:
-	// https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK
+	/*
+	 * AMD GPU Services (AGS) library
+	 *
+	 * Reference:
+	 * https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK
+	 */
 	enum AGS_RETURN_CODE
 	{
 		AGS_SUCCESS,
@@ -625,6 +629,53 @@ namespace bgfx { namespace d3d11
 	static MultiDrawIndirectFn multiDrawInstancedIndirect;
 	static MultiDrawIndirectFn multiDrawIndexedInstancedIndirect;
 
+	/*
+	 * NVAPI
+	 *
+	 * Reference:
+	 * http://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/index.html
+	 * https://github.com/jNizM/AHK_NVIDIA_NvAPI/blob/master/info/NvAPI_IDs.txt
+	 */
+	struct NvDisplayHandle;
+
+	enum NvApiStatus
+	{
+		NVAPI_OK    =  0,
+		NVAPI_ERROR = -1,
+	};
+
+	struct NvMemoryInfoV2
+	{
+		NvMemoryInfoV2()
+			: version(sizeof(NvMemoryInfoV2) | (2 << 16) )
+		{
+		}
+
+		uint32_t version;
+		uint32_t dedicatedVideoMemory;
+		uint32_t availableDedicatedVideoMemory;
+		uint32_t systemVideoMemory;
+		uint32_t sharedSystemMemory;
+		uint32_t curAvailableDedicatedVideoMemory;
+	};
+
+	typedef void*       (__cdecl* PFN_NVAPI_QUERYINTERFACE)(uint32_t _functionOffset);
+	typedef NvApiStatus (__cdecl* PFN_NVAPI_INITIALIZE)();
+	typedef NvApiStatus (__cdecl* PFN_NVAPI_UNLOAD)();
+	typedef NvApiStatus (__cdecl* PFN_NVAPI_ENUMNVIDIADISPLAYHANDLE)(uint32_t _index, NvDisplayHandle** _handle);
+	typedef NvApiStatus (__cdecl* PFN_NVAPI_GPU_GETMEMORYINFO)(NvDisplayHandle* _handle, NvMemoryInfoV2* _memoryInfo);
+
+#define NVAPI_INITIALIZE              UINT32_C(0x0150e828)
+#define NVAPI_UNLOAD                  UINT32_C(0xd22bdd7e)
+#define NVAPI_ENUMNVIDIADISPLAYHANDLE UINT32_C(0x9abdd40d)
+#define NVAPI_GPU_GETMEMORYINFO       UINT32_C(0x774AA982) //UINT32_C(0x07f9b368)
+
+	static PFN_NVAPI_QUERYINTERFACE          nvApiQueryInterface;
+	static PFN_NVAPI_INITIALIZE              nvApiInitialize;
+	static PFN_NVAPI_UNLOAD                  nvApiUnload;
+	static PFN_NVAPI_ENUMNVIDIADISPLAYHANDLE nvApiEnumNvidiaDisplayHandle;
+	static PFN_NVAPI_GPU_GETMEMORYINFO       nvApiGetMemoryInfo;
+
 #if USE_D3D11_DYNAMIC_LIB
 	static PFN_D3D11_CREATE_DEVICE  D3D11CreateDevice;
 	static PFN_CREATE_DXGI_FACTORY  CreateDXGIFactory;
@@ -668,6 +719,8 @@ namespace bgfx { namespace d3d11
 			, m_renderdocdll(NULL)
 			, m_agsdll(NULL)
 			, m_ags(NULL)
+			, m_nvapidll(NULL)
+			, m_nvDisplayHandle(NULL)
 			, m_driverType(D3D_DRIVER_TYPE_NULL)
 			, m_featureLevel(D3D_FEATURE_LEVEL(0) )
 			, m_adapter(NULL)
@@ -737,11 +790,11 @@ namespace bgfx { namespace d3d11
 			m_ags = NULL;
 			m_agsdll = bx::dlopen(
 #if BX_ARCH_32BIT
-						"amd_ags_x86.dll"
+				"amd_ags_x86.dll"
 #else
-						"amd_ags_x64.dll"
+				"amd_ags_x64.dll"
 #endif // BX_ARCH_32BIT
-						);
+				);
 			if (NULL != m_agsdll)
 			{
 				agsInit   = (PFN_AGS_INIT  )bx::dlsym(m_agsdll, "agsInit");
@@ -814,6 +867,59 @@ namespace bgfx { namespace d3d11
 				}
 			}
 
+			m_nvDisplayHandle = NULL;
+			m_nvapidll = bx::dlopen(
+#if BX_ARCH_32BIT
+				"nvapi.dll"
+#else
+				"nvapi64.dll"
+#endif // BX_ARCH_32BIT
+				);
+
+			if (NULL != m_nvapidll)
+			{
+				nvApiQueryInterface = (PFN_NVAPI_QUERYINTERFACE)bx::dlsym(m_nvapidll, "nvapi_QueryInterface");
+
+				bool initialized = NULL != nvApiQueryInterface;
+
+				if (initialized)
+				{
+					nvApiInitialize              = (PFN_NVAPI_INITIALIZE             )nvApiQueryInterface(NVAPI_INITIALIZE);
+					nvApiUnload                  = (PFN_NVAPI_UNLOAD                 )nvApiQueryInterface(NVAPI_UNLOAD);
+					nvApiEnumNvidiaDisplayHandle = (PFN_NVAPI_ENUMNVIDIADISPLAYHANDLE)nvApiQueryInterface(NVAPI_ENUMNVIDIADISPLAYHANDLE);
+					nvApiGetMemoryInfo           = (PFN_NVAPI_GPU_GETMEMORYINFO      )nvApiQueryInterface(NVAPI_GPU_GETMEMORYINFO);
+
+					initialized &= true
+						&& NULL != nvApiInitialize
+						&& NULL != nvApiUnload
+						&& NULL != nvApiEnumNvidiaDisplayHandle
+						&& NULL != nvApiGetMemoryInfo
+						;
+
+					if (initialized)
+					{
+						initialized &= true
+							&& NVAPI_OK == nvApiInitialize()
+							&& NVAPI_OK == nvApiEnumNvidiaDisplayHandle(0, &m_nvDisplayHandle)
+							;
+					 }
+
+					if (!initialized)
+					{
+						m_nvDisplayHandle = NULL;
+						nvApiUnload();
+					}
+				}
+
+				if (!initialized)
+				{
+					bx::dlclose(m_nvapidll);
+					m_nvapidll = NULL;
+				}
+
+				BX_TRACE("NVAPI supported.");
+			}
+
 #if USE_D3D11_DYNAMIC_LIB
 			m_d3d11dll = bx::dlopen("d3d11.dll");
 
@@ -1702,12 +1808,24 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 
 			case ErrorState::Default:
 			default:
+				if (NULL != m_nvDisplayHandle)
+				{
+					nvApiUnload();
+					m_nvDisplayHandle = NULL;
+				}
+
+				bx::dlclose(m_nvapidll);
+				m_nvapidll = NULL;
+
 				if (NULL != m_ags)
 				{
 					agsDeInit(m_ags);
+					m_ags = NULL;
 				}
+
 				bx::dlclose(m_agsdll);
 				m_agsdll = NULL;
+
 				unloadRenderDoc(m_renderdocdll);
 				m_ovr.shutdown();
 				break;
@@ -1721,6 +1839,15 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 			preReset();
 			m_ovr.shutdown();
 
+			if (NULL != m_nvDisplayHandle)
+			{
+				nvApiUnload();
+				m_nvDisplayHandle = NULL;
+			}
+
+			bx::dlclose(m_nvapidll);
+			m_nvapidll = NULL;
+
 			if (NULL != m_ags)
 			{
 				agsDeInit(m_ags);
@@ -3652,6 +3779,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		void* m_renderdocdll;
 		void* m_agsdll;
 		AGSContext* m_ags;
+		void* m_nvapidll;
+		NvDisplayHandle* m_nvDisplayHandle;
 
 
 		D3D_DRIVER_TYPE   m_driverType;
@@ -6479,6 +6608,23 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		perfStats.numDraw       = statsKeyType[0];
 		perfStats.numCompute    = statsKeyType[1];
 		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
+
+		if (NULL != m_nvDisplayHandle)
+		{
+			NvMemoryInfoV2 memInfo;
+			if (NVAPI_OK == nvApiGetMemoryInfo(m_nvDisplayHandle, &memInfo) )
+			{
+				perfStats.gpuMemoryMax  = 1024 *  memInfo.availableDedicatedVideoMemory;
+				perfStats.gpuMemoryUsed = 1024 * (memInfo.availableDedicatedVideoMemory - memInfo.curAvailableDedicatedVideoMemory);
+//				BX_TRACE("            dedicatedVideoMemory: %d KiB", memInfo.dedicatedVideoMemory);
+//				BX_TRACE("   availableDedicatedVideoMemory: %d KiB", memInfo.availableDedicatedVideoMemory);
+//				BX_TRACE("               systemVideoMemory: %d KiB", memInfo.systemVideoMemory);
+//				BX_TRACE("              sharedSystemMemory: %d KiB", memInfo.sharedSystemMemory);
+//				BX_TRACE("curAvailableDedicatedVideoMemory: %d KiB", memInfo.curAvailableDedicatedVideoMemory);
+			}
+		}
 
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
 		{

+ 2 - 0
src/renderer_d3d12.cpp

@@ -5749,6 +5749,8 @@ data.NumQualityLevels = 0;
 		perfStats.numDraw       = statsKeyType[0];
 		perfStats.numCompute    = statsKeyType[1];
 		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
 
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
 		{

+ 2 - 0
src/renderer_d3d9.cpp

@@ -4382,6 +4382,8 @@ namespace bgfx { namespace d3d9
 		perfStats.numDraw       = statsKeyType[0];
 		perfStats.numCompute    = statsKeyType[1];
 		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
 
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
 		{

+ 2 - 0
src/renderer_gl.cpp

@@ -7631,6 +7631,8 @@ namespace bgfx { namespace gl
 		perfStats.numDraw       = statsKeyType[0];
 		perfStats.numCompute    = statsKeyType[1];
 		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
 
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
 		{

+ 2 - 0
src/renderer_mtl.mm

@@ -3930,6 +3930,8 @@ namespace bgfx { namespace mtl
 		perfStats.numDraw       = statsKeyType[0];
 		perfStats.numCompute    = statsKeyType[1];
 		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
 
 		rce.setTriangleFillMode(MTLTriangleFillModeFill);
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )

+ 2 - 0
src/renderer_vk.cpp

@@ -4396,6 +4396,8 @@ BX_UNUSED(presentMin, presentMax);
 //		perfStats.numDraw       = statsKeyType[0];
 //		perfStats.numCompute    = statsKeyType[1];
 //		perfStats.maxGpuLatency = maxGpuLatency;
+		perfStats.gpuMemoryMax  = -INT64_MAX;
+		perfStats.gpuMemoryUsed = -INT64_MAX;
 
 		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
 		{