From aa567d3d72a6a342231b0ab9dbd515f10d48ceba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 26 Sep 2017 18:09:15 -0700 Subject: [PATCH] D3D11: Added GPU memory stats. --- include/bgfx/bgfx.h | 17 +++-- include/bgfx/c99/bgfx.h | 17 +++-- include/bgfx/defines.h | 2 +- src/renderer_d3d11.cpp | 156 ++++++++++++++++++++++++++++++++++++++-- src/renderer_d3d12.cpp | 2 + src/renderer_d3d9.cpp | 2 + src/renderer_gl.cpp | 2 + src/renderer_mtl.mm | 2 + src/renderer_vk.cpp | 2 + 9 files changed, 182 insertions(+), 20 deletions(-) diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 49821b2bb..cb8a2d225 100644 --- a/include/bgfx/bgfx.h +++ b/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. diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 3bd316b4a..48bf83f23 100644 --- a/include/bgfx/c99/bgfx.h +++ b/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; diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index 660cfb67c..989d56d09 100644 --- a/include/bgfx/defines.h +++ b/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. diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 61946d252..5ce95a8b6 100644 --- a/src/renderer_d3d11.cpp +++ b/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) ) { diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 8d8ade928..ed428ca69 100644 --- a/src/renderer_d3d12.cpp +++ b/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) ) { diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index d81b8e8f7..f53f3beba 100644 --- a/src/renderer_d3d9.cpp +++ b/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) ) { diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 21f24bef0..6a3f044b2 100644 --- a/src/renderer_gl.cpp +++ b/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) ) { diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 89eadac7e..721040d17 100644 --- a/src/renderer_mtl.mm +++ b/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) ) diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 13770de01..bb9241a93 100644 --- a/src/renderer_vk.cpp +++ b/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) ) {