nvapi.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Copyright 2011-2018 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "bgfx_p.h"
  6. #include "nvapi.h"
  7. namespace bgfx
  8. {
  9. /*
  10. * NVAPI
  11. *
  12. * Reference:
  13. * http://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/index.html
  14. * https://github.com/jNizM/AHK_NVIDIA_NvAPI/blob/master/info/NvAPI_IDs.txt
  15. */
  16. struct NvPhysicalGpuHandle;
  17. #define NVAPI_MAX_PHYSICAL_GPUS 64
  18. #if BX_PLATFORM_WINDOWS
  19. # define NVAPICALL __cdecl
  20. #else
  21. # define NVAPICALL
  22. #endif // BX_PLATFORM_WINDOWS
  23. enum NvApiStatus
  24. {
  25. NVAPI_OK = 0,
  26. NVAPI_ERROR = -1,
  27. };
  28. struct NvMemoryInfoV2
  29. {
  30. NvMemoryInfoV2()
  31. : version(sizeof(NvMemoryInfoV2) | (2 << 16) )
  32. {
  33. }
  34. uint32_t version;
  35. uint32_t dedicatedVideoMemory;
  36. uint32_t availableDedicatedVideoMemory;
  37. uint32_t systemVideoMemory;
  38. uint32_t sharedSystemMemory;
  39. uint32_t curAvailableDedicatedVideoMemory;
  40. };
  41. typedef void* (NVAPICALL* PFN_NVAPI_QUERYINTERFACE)(uint32_t _functionOffset);
  42. typedef NvApiStatus (NVAPICALL* PFN_NVAPI_INITIALIZE)();
  43. typedef NvApiStatus (NVAPICALL* PFN_NVAPI_UNLOAD)();
  44. typedef NvApiStatus (NVAPICALL* PFN_NVAPI_ENUMPHYSICALGPUS)(NvPhysicalGpuHandle* _handle[NVAPI_MAX_PHYSICAL_GPUS], uint32_t* _gpuCount);
  45. typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETMEMORYINFO)(NvPhysicalGpuHandle* _handle, NvMemoryInfoV2* _memoryInfo);
  46. typedef NvApiStatus (NVAPICALL* PFN_NVAPI_GPUGETFULLNAME)(NvPhysicalGpuHandle* _physicalGpu, char _name[64]);
  47. #define NVAPI_INITIALIZE UINT32_C(0x0150e828)
  48. #define NVAPI_UNLOAD UINT32_C(0xd22bdd7e)
  49. #define NVAPI_ENUMPHYSICALGPUS UINT32_C(0xe5ac921f)
  50. #define NVAPI_GPUGETMEMORYINFO UINT32_C(0x07f9b368)
  51. #define NVAPI_GPUGETFULLNAME UINT32_C(0xceee8e9f)
  52. #define NVAPI_MULTIDRAWINSTANCEDINDIRECT UINT32_C(0xd4e26bbf)
  53. #define NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT UINT32_C(0x59e890f9)
  54. static PFN_NVAPI_QUERYINTERFACE nvApiQueryInterface;
  55. static PFN_NVAPI_INITIALIZE nvApiInitialize;
  56. static PFN_NVAPI_UNLOAD nvApiUnload;
  57. static PFN_NVAPI_ENUMPHYSICALGPUS nvApiEnumPhysicalGPUs;
  58. static PFN_NVAPI_GPUGETMEMORYINFO nvApiGpuGetMemoryInfo;
  59. static PFN_NVAPI_GPUGETFULLNAME nvApiGpuGetFullName;
  60. /*
  61. * NVIDIA Aftermath
  62. *
  63. * Reference:
  64. * https://developer.nvidia.com/nvidia-aftermath
  65. */
  66. typedef int32_t (*PFN_NVAFTERMATH_DX12_INITIALIZE)(int32_t _version, int32_t _flags, const ID3D12Device* _device);
  67. typedef int32_t (*PFN_NVAFTERMATH_DX12_CREATECONTEXTHANDLE)(const ID3D12CommandList* _commandList, NvAftermathContextHandle** _outContextHandle);
  68. typedef int32_t (*PFN_NVAFTERMATH_RELEASECONTEXTHANDLE)(const NvAftermathContextHandle* _contextHandle);
  69. typedef int32_t (*PFN_NVAFTERMATH_SETEVENTMARKER)(const NvAftermathContextHandle* _contextHandle, const void* _markerData, uint32_t _markerSize);
  70. typedef int32_t (*PFN_NVAFTERMATH_GETDATA)(uint32_t _numContexts, const NvAftermathContextHandle** _contextHandles, void* _outContextData);
  71. typedef int32_t (*PFN_NVAFTERMATH_GETDEVICESTATUS)(void* _outStatus);
  72. typedef int32_t (*PFN_NVAFTERMATH_GETPAGEFAULTINFORMATION)(void* _outPageFaultInformation);
  73. static PFN_NVAFTERMATH_DX12_INITIALIZE nvAftermathDx12Initialize;
  74. static PFN_NVAFTERMATH_DX12_CREATECONTEXTHANDLE nvAftermathDx12CreateContextHandle;
  75. static PFN_NVAFTERMATH_RELEASECONTEXTHANDLE nvAftermathReleaseContextHandle;
  76. static PFN_NVAFTERMATH_SETEVENTMARKER nvAftermathSetEventMarker;
  77. static PFN_NVAFTERMATH_GETDATA nvAftermathGetData;
  78. static PFN_NVAFTERMATH_GETDEVICESTATUS nvAftermathGetDeviceStatus;
  79. static PFN_NVAFTERMATH_GETPAGEFAULTINFORMATION nvAftermathGetPageFaultInformation;
  80. NvApi::NvApi()
  81. : m_nvApiDll(NULL)
  82. , m_nvGpu(NULL)
  83. , m_nvAftermathDll(NULL)
  84. , m_aftermathHandle(NULL)
  85. {
  86. }
  87. void NvApi::init()
  88. {
  89. m_nvGpu = NULL;
  90. m_nvApiDll = bx::dlopen(
  91. "nvapi"
  92. #if BX_ARCH_64BIT
  93. "64"
  94. #endif // BX_ARCH_32BIT
  95. ".dll"
  96. );
  97. if (NULL != m_nvApiDll)
  98. {
  99. nvApiQueryInterface = (PFN_NVAPI_QUERYINTERFACE)bx::dlsym(m_nvApiDll, "nvapi_QueryInterface");
  100. bool initialized = NULL != nvApiQueryInterface;
  101. if (initialized)
  102. {
  103. nvApiInitialize = (PFN_NVAPI_INITIALIZE )nvApiQueryInterface(NVAPI_INITIALIZE);
  104. nvApiUnload = (PFN_NVAPI_UNLOAD )nvApiQueryInterface(NVAPI_UNLOAD);
  105. nvApiEnumPhysicalGPUs = (PFN_NVAPI_ENUMPHYSICALGPUS)nvApiQueryInterface(NVAPI_ENUMPHYSICALGPUS);
  106. nvApiGpuGetMemoryInfo = (PFN_NVAPI_GPUGETMEMORYINFO)nvApiQueryInterface(NVAPI_GPUGETMEMORYINFO);
  107. nvApiGpuGetFullName = (PFN_NVAPI_GPUGETFULLNAME )nvApiQueryInterface(NVAPI_GPUGETFULLNAME);
  108. nvApiD3D11MultiDrawInstancedIndirect = (PFN_NVAPI_MULTIDRAWINDIRECT)nvApiQueryInterface(NVAPI_MULTIDRAWINSTANCEDINDIRECT);
  109. nvApiD3D11MultiDrawIndexedInstancedIndirect = (PFN_NVAPI_MULTIDRAWINDIRECT)nvApiQueryInterface(NVAPI_MULTIDRAWINDEXEDINSTANCEDINDIRECT);
  110. initialized = true
  111. && NULL != nvApiInitialize
  112. && NULL != nvApiUnload
  113. && NULL != nvApiEnumPhysicalGPUs
  114. && NULL != nvApiGpuGetMemoryInfo
  115. && NULL != nvApiGpuGetFullName
  116. && NVAPI_OK == nvApiInitialize()
  117. ;
  118. if (initialized)
  119. {
  120. NvPhysicalGpuHandle* physicalGpus[NVAPI_MAX_PHYSICAL_GPUS];
  121. uint32_t numGpus = 0;
  122. nvApiEnumPhysicalGPUs(physicalGpus, &numGpus);
  123. initialized = 0 < numGpus;
  124. if (initialized)
  125. {
  126. m_nvGpu = physicalGpus[0];
  127. }
  128. char name[64];
  129. nvApiGpuGetFullName(m_nvGpu, name);
  130. BX_TRACE("%s", name);
  131. }
  132. initialized = NULL != m_nvGpu;
  133. if (!initialized)
  134. {
  135. nvApiUnload();
  136. }
  137. }
  138. if (!initialized)
  139. {
  140. bx::dlclose(m_nvApiDll);
  141. m_nvApiDll = NULL;
  142. }
  143. BX_WARN(!initialized, "NVAPI supported.");
  144. }
  145. }
  146. void NvApi::shutdown()
  147. {
  148. if (NULL != m_nvGpu)
  149. {
  150. nvApiUnload();
  151. m_nvGpu = NULL;
  152. }
  153. if (NULL != m_nvApiDll)
  154. {
  155. bx::dlclose(m_nvApiDll);
  156. m_nvApiDll = NULL;
  157. }
  158. shutdownAftermath();
  159. }
  160. void NvApi::getMemoryInfo(int64_t& _gpuMemoryUsed, int64_t& _gpuMemoryMax)
  161. {
  162. if (NULL != m_nvGpu)
  163. {
  164. NvMemoryInfoV2 memInfo;
  165. NvApiStatus status = nvApiGpuGetMemoryInfo(m_nvGpu, &memInfo);
  166. if (NVAPI_OK == status)
  167. {
  168. _gpuMemoryMax = 1024 * int64_t(memInfo.availableDedicatedVideoMemory);
  169. _gpuMemoryUsed = 1024 * int64_t(memInfo.availableDedicatedVideoMemory - memInfo.curAvailableDedicatedVideoMemory);
  170. // BX_TRACE(" dedicatedVideoMemory: %d KiB", memInfo.dedicatedVideoMemory);
  171. // BX_TRACE(" availableDedicatedVideoMemory: %d KiB", memInfo.availableDedicatedVideoMemory);
  172. // BX_TRACE(" systemVideoMemory: %d KiB", memInfo.systemVideoMemory);
  173. // BX_TRACE(" sharedSystemMemory: %d KiB", memInfo.sharedSystemMemory);
  174. // BX_TRACE("curAvailableDedicatedVideoMemory: %d KiB", memInfo.curAvailableDedicatedVideoMemory);
  175. }
  176. }
  177. else
  178. {
  179. _gpuMemoryMax = -INT64_MAX;
  180. _gpuMemoryUsed = -INT64_MAX;
  181. }
  182. }
  183. bool NvApi::initAftermath(const ID3D12Device* _device, const ID3D12CommandList* _commandList)
  184. {
  185. m_nvAftermathDll = bx::dlopen(
  186. "GFSDK_Aftermath_Lib."
  187. #if BX_ARCH_32BIT
  188. "x86"
  189. #else
  190. "x64"
  191. #endif // BX_ARCH_32BIT
  192. ".dll"
  193. );
  194. if (NULL != m_nvAftermathDll)
  195. {
  196. nvAftermathDx12Initialize = (PFN_NVAFTERMATH_DX12_INITIALIZE )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_DX12_Initialize");
  197. nvAftermathDx12CreateContextHandle = (PFN_NVAFTERMATH_DX12_CREATECONTEXTHANDLE)bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_DX12_CreateContextHandle");
  198. nvAftermathReleaseContextHandle = (PFN_NVAFTERMATH_RELEASECONTEXTHANDLE )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_ReleaseContextHandle");
  199. nvAftermathSetEventMarker = (PFN_NVAFTERMATH_SETEVENTMARKER )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_SetEventMarker");
  200. nvAftermathGetData = (PFN_NVAFTERMATH_GETDATA )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_GetData");
  201. nvAftermathGetDeviceStatus = (PFN_NVAFTERMATH_GETDEVICESTATUS )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_GetDeviceStatus");
  202. nvAftermathGetPageFaultInformation = (PFN_NVAFTERMATH_GETPAGEFAULTINFORMATION )bx::dlsym(m_nvAftermathDll, "GFSDK_Aftermath_GetPageFaultInformation");
  203. bool initialized = true
  204. && NULL != nvAftermathDx12Initialize
  205. && NULL != nvAftermathDx12CreateContextHandle
  206. && NULL != nvAftermathReleaseContextHandle
  207. && NULL != nvAftermathSetEventMarker
  208. && NULL != nvAftermathGetData
  209. && NULL != nvAftermathGetDeviceStatus
  210. && NULL != nvAftermathGetPageFaultInformation
  211. ;
  212. if (initialized)
  213. {
  214. int32_t result;
  215. result = nvAftermathDx12Initialize(0x13, 1, _device);
  216. if (1 == result)
  217. {
  218. result = nvAftermathDx12CreateContextHandle(_commandList, &m_aftermathHandle);
  219. BX_WARN(1 == result, "%x", result);
  220. if (1 == result)
  221. {
  222. return true;
  223. }
  224. }
  225. }
  226. shutdownAftermath();
  227. }
  228. return false;
  229. }
  230. void NvApi::shutdownAftermath()
  231. {
  232. if (NULL != m_nvAftermathDll)
  233. {
  234. if (NULL != m_aftermathHandle)
  235. {
  236. nvAftermathReleaseContextHandle(m_aftermathHandle);
  237. m_aftermathHandle = NULL;
  238. }
  239. bx::dlclose(m_nvAftermathDll);
  240. m_nvAftermathDll = NULL;
  241. }
  242. }
  243. #define NVA_CHECK(_call) \
  244. BX_MACRO_BLOCK_BEGIN \
  245. int32_t __result__ = _call; \
  246. BX_CHECK(1 == __result__, #_call " FAILED 0x%08x\n", __result__); \
  247. BX_UNUSED(__result__); \
  248. BX_MACRO_BLOCK_END
  249. void NvApi::setMarker(const bx::StringView& _marker)
  250. {
  251. if (NULL != m_aftermathHandle)
  252. {
  253. NVA_CHECK(nvAftermathSetEventMarker(m_aftermathHandle, _marker.getPtr(), _marker.getLength() ) );
  254. }
  255. }
  256. } // namespace bgfx