pix3_win.h (13168B)
1 // Copyright (c) Microsoft Corporation. All rights reserved. 2 3 /*==========================================================================; 4 * 5 * Copyright (C) Microsoft Corporation. All Rights Reserved. 6 * 7 * File: PIX3_win.h 8 * Content: PIX include file 9 * Don't include this file directly - use pix3.h 10 * 11 ****************************************************************************/ 12 13 #pragma once 14 15 #ifndef _PIX3_H_ 16 #error Don't include this file directly - use pix3.h 17 #endif 18 19 #ifndef _PIX3_WIN_H_ 20 #define _PIX3_WIN_H_ 21 22 // PIXEventsThreadInfo is defined in PIXEventsCommon.h 23 struct PIXEventsThreadInfo; 24 25 extern "C" PIXEventsThreadInfo* WINAPI PIXGetThreadInfo() noexcept; 26 27 #if defined(USE_PIX) && defined(USE_PIX_SUPPORTED_ARCHITECTURE) 28 // Notifies PIX that an event handle was set as a result of a D3D12 fence being signaled. 29 // The event specified must have the same handle value as the handle 30 // used in ID3D12Fence::SetEventOnCompletion. 31 extern "C" void WINAPI PIXNotifyWakeFromFenceSignal(_In_ HANDLE event); 32 33 // Notifies PIX that a block of memory was allocated 34 extern "C" void WINAPI PIXRecordMemoryAllocationEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata); 35 36 // Notifies PIX that a block of memory was freed 37 extern "C" void WINAPI PIXRecordMemoryFreeEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata); 38 39 #else 40 41 // Eliminate these APIs when not using PIX 42 inline void PIXRecordMemoryAllocationEvent(USHORT, void*, size_t, UINT64) {} 43 inline void PIXRecordMemoryFreeEvent(USHORT, void*, size_t, UINT64) {} 44 45 #endif 46 47 // The following defines denote the different metadata values that have been used 48 // by tools to denote how to parse pix marker event data. The first two values 49 // are legacy values. 50 #define WINPIX_EVENT_UNICODE_VERSION 0 51 #define WINPIX_EVENT_ANSI_VERSION 1 52 #define WINPIX_EVENT_PIX3BLOB_VERSION 2 53 54 #define D3D12_EVENT_METADATA WINPIX_EVENT_PIX3BLOB_VERSION 55 56 __forceinline UINT64 PIXGetTimestampCounter() 57 { 58 LARGE_INTEGER time = {}; 59 QueryPerformanceCounter(&time); 60 return static_cast<UINT64>(time.QuadPart); 61 } 62 63 enum PIXHUDOptions 64 { 65 PIX_HUD_SHOW_ON_ALL_WINDOWS = 0x1, 66 PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY = 0x2, 67 PIX_HUD_SHOW_ON_NO_WINDOWS = 0x4 68 }; 69 DEFINE_ENUM_FLAG_OPERATORS(PIXHUDOptions); 70 71 #if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && defined(USE_PIX) 72 73 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) 74 75 #include <shlobj.h> 76 #include <strsafe.h> 77 #include <knownfolders.h> 78 #include <shellapi.h> 79 80 #define PIXERRORCHECK(value) do { \ 81 if (FAILED(value)) \ 82 return nullptr; \ 83 } while(0) 84 85 namespace PixImpl 86 { 87 #ifndef PIX3_WIN_UNIT_TEST 88 89 __forceinline BOOL GetModuleHandleExW( 90 DWORD dwFlags, 91 LPCWSTR lpModuleName, 92 HMODULE* phModule) 93 { 94 return ::GetModuleHandleExW(dwFlags, lpModuleName, phModule); 95 } 96 97 __forceinline HRESULT SHGetKnownFolderPath( 98 REFKNOWNFOLDERID rfid, 99 DWORD dwFlags, 100 HANDLE hToken, 101 PWSTR* ppszPath) 102 { 103 return ::SHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); 104 } 105 106 __forceinline void CoTaskMemFree(LPVOID pv) 107 { 108 return ::CoTaskMemFree(pv); 109 } 110 111 __forceinline HANDLE FindFirstFileW( 112 LPCWSTR lpFileName, 113 LPWIN32_FIND_DATAW lpFindFileData) 114 { 115 return ::FindFirstFileW(lpFileName, lpFindFileData); 116 } 117 118 __forceinline DWORD GetFileAttributesW(LPCWSTR lpFileName) 119 { 120 return ::GetFileAttributesW(lpFileName); 121 } 122 123 __forceinline BOOL FindNextFileW( 124 HANDLE hFindFile, 125 LPWIN32_FIND_DATAW lpFindFileData) 126 { 127 return ::FindNextFileW(hFindFile, lpFindFileData); 128 } 129 130 __forceinline BOOL FindClose(HANDLE hFindFile) 131 { 132 return ::FindClose(hFindFile); 133 } 134 135 __forceinline HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, DWORD flags) 136 { 137 return ::LoadLibraryExW(lpLibFileName, NULL, flags); 138 } 139 140 #endif // !PIX3_WIN_UNIT_TESTS 141 142 __forceinline void * GetGpuCaptureFunctionPtr(LPCSTR fnName) noexcept 143 { 144 HMODULE module = GetModuleHandleW(L"WinPixGpuCapturer.dll"); 145 if (module == NULL) 146 { 147 return nullptr; 148 } 149 150 auto fn = (void*)GetProcAddress(module, fnName); 151 if (fn == nullptr) 152 { 153 return nullptr; 154 } 155 156 return fn; 157 } 158 159 __forceinline void* GetTimingCaptureFunctionPtr(LPCSTR fnName) noexcept 160 { 161 HMODULE module = GetModuleHandleW(L"WinPixTimingCapturer.dll"); 162 if (module == NULL) 163 { 164 return nullptr; 165 } 166 167 auto fn = (void*)GetProcAddress(module, fnName); 168 if (fn == nullptr) 169 { 170 return nullptr; 171 } 172 173 return fn; 174 } 175 176 __forceinline HMODULE PIXLoadLatestCapturerLibrary(wchar_t const* capturerDllName, DWORD flags) 177 { 178 HMODULE libHandle{}; 179 180 if (PixImpl::GetModuleHandleExW(0, capturerDllName, &libHandle)) 181 { 182 return libHandle; 183 } 184 185 LPWSTR programFilesPath = nullptr; 186 if (FAILED(PixImpl::SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath))) 187 { 188 PixImpl::CoTaskMemFree(programFilesPath); 189 return nullptr; 190 } 191 192 wchar_t pixSearchPath[MAX_PATH]; 193 194 if (FAILED(StringCchCopyW(pixSearchPath, MAX_PATH, programFilesPath))) 195 { 196 PixImpl::CoTaskMemFree(programFilesPath); 197 return nullptr; 198 } 199 PixImpl::CoTaskMemFree(programFilesPath); 200 201 PIXERRORCHECK(StringCchCatW(pixSearchPath, MAX_PATH, L"\\Microsoft PIX\\*")); 202 203 WIN32_FIND_DATAW findData; 204 bool foundPixInstallation = false; 205 wchar_t newestVersionFound[MAX_PATH]; 206 wchar_t output[MAX_PATH]; 207 wchar_t possibleOutput[MAX_PATH]; 208 209 HANDLE hFind = PixImpl::FindFirstFileW(pixSearchPath, &findData); 210 if (hFind != INVALID_HANDLE_VALUE) 211 { 212 do 213 { 214 if (((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) && 215 (findData.cFileName[0] != '.')) 216 { 217 if (!foundPixInstallation || wcscmp(newestVersionFound, findData.cFileName) <= 0) 218 { 219 // length - 1 to get rid of the wildcard character in the search path 220 PIXERRORCHECK(StringCchCopyNW(possibleOutput, MAX_PATH, pixSearchPath, wcslen(pixSearchPath) - 1)); 221 PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, findData.cFileName)); 222 PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, L"\\")); 223 PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, capturerDllName)); 224 225 DWORD result = PixImpl::GetFileAttributesW(possibleOutput); 226 227 if (result != INVALID_FILE_ATTRIBUTES && !(result & FILE_ATTRIBUTE_DIRECTORY)) 228 { 229 foundPixInstallation = true; 230 PIXERRORCHECK(StringCchCopyW(newestVersionFound, _countof(newestVersionFound), findData.cFileName)); 231 PIXERRORCHECK(StringCchCopyW(output, _countof(possibleOutput), possibleOutput)); 232 } 233 } 234 } 235 } while (PixImpl::FindNextFileW(hFind, &findData) != 0); 236 } 237 238 PixImpl::FindClose(hFind); 239 240 if (!foundPixInstallation) 241 { 242 SetLastError(ERROR_FILE_NOT_FOUND); 243 return nullptr; 244 } 245 246 return PixImpl::LoadLibraryExW(output, flags); 247 } 248 } 249 250 #undef PIXERRORCHECK 251 252 __forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() 253 { 254 return PixImpl::PIXLoadLatestCapturerLibrary( 255 L"WinPixGpuCapturer.dll", 256 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); 257 } 258 259 __forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary() 260 { 261 return PixImpl::PIXLoadLatestCapturerLibrary( 262 L"WinPixTimingCapturer.dll", 263 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); 264 } 265 266 __forceinline HRESULT WINAPI PIXSetTargetWindow(HWND hwnd) 267 { 268 typedef void(WINAPI* SetGlobalTargetWindowFn)(HWND); 269 270 auto fn = (SetGlobalTargetWindowFn)PixImpl::GetGpuCaptureFunctionPtr("SetGlobalTargetWindow"); 271 if (fn == nullptr) 272 { 273 return HRESULT_FROM_WIN32(GetLastError()); 274 } 275 276 fn(hwnd); 277 return S_OK; 278 } 279 280 __forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames) 281 { 282 typedef HRESULT(WINAPI* CaptureNextFrameFn)(PCWSTR, UINT32); 283 284 auto fn = (CaptureNextFrameFn)PixImpl::GetGpuCaptureFunctionPtr("CaptureNextFrame"); 285 if (fn == nullptr) 286 { 287 return HRESULT_FROM_WIN32(GetLastError()); 288 } 289 290 return fn(fileName, numFrames); 291 } 292 293 extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) 294 { 295 if (captureFlags == PIX_CAPTURE_GPU) 296 { 297 typedef HRESULT(WINAPI* BeginProgrammaticGpuCaptureFn)(const PPIXCaptureParameters); 298 299 auto fn = (BeginProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("BeginProgrammaticGpuCapture"); 300 if (fn == nullptr) 301 { 302 return HRESULT_FROM_WIN32(GetLastError()); 303 } 304 305 return fn(captureParameters); 306 } 307 else if (captureFlags == PIX_CAPTURE_TIMING) 308 { 309 typedef HRESULT(WINAPI* BeginProgrammaticTimingCaptureFn)(void const*, UINT64); 310 311 auto fn = (BeginProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("BeginProgrammaticTimingCapture"); 312 if (fn == nullptr) 313 { 314 return HRESULT_FROM_WIN32(GetLastError()); 315 } 316 317 return fn(&captureParameters->TimingCaptureParameters, sizeof(captureParameters->TimingCaptureParameters)); 318 } 319 else 320 { 321 return E_NOTIMPL; 322 } 323 } 324 325 extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL discard) 326 { 327 UNREFERENCED_PARAMETER(discard); 328 329 // We can't tell if the user wants to end a GPU Capture or a Timing Capture. 330 // The user shouldn't have both WinPixGpuCapturer and WinPixTimingCapturer loaded in the process though, 331 // so we can just look for one of them and call it. 332 typedef HRESULT(WINAPI* EndProgrammaticGpuCaptureFn)(void); 333 auto gpuFn = (EndProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("EndProgrammaticGpuCapture"); 334 if (gpuFn != NULL) 335 { 336 return gpuFn(); 337 } 338 339 typedef HRESULT(WINAPI* EndProgrammaticTimingCaptureFn)(BOOL); 340 auto timingFn = (EndProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("EndProgrammaticTimingCapture"); 341 if (timingFn != NULL) 342 { 343 return timingFn(discard); 344 } 345 346 return HRESULT_FROM_WIN32(GetLastError()); 347 } 348 349 __forceinline HRESULT WINAPI PIXForceD3D11On12() 350 { 351 typedef HRESULT (WINAPI* ForceD3D11On12Fn)(void); 352 353 auto fn = (ForceD3D11On12Fn)PixImpl::GetGpuCaptureFunctionPtr("ForceD3D11On12"); 354 if (fn == NULL) 355 { 356 return HRESULT_FROM_WIN32(GetLastError()); 357 } 358 359 return fn(); 360 } 361 362 __forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions hudOptions) 363 { 364 typedef HRESULT(WINAPI* SetHUDOptionsFn)(PIXHUDOptions); 365 366 auto fn = (SetHUDOptionsFn)PixImpl::GetGpuCaptureFunctionPtr("SetHUDOptions"); 367 if (fn == NULL) 368 { 369 return HRESULT_FROM_WIN32(GetLastError()); 370 } 371 372 return fn(hudOptions); 373 } 374 375 __forceinline bool WINAPI PIXIsAttachedForGpuCapture() 376 { 377 typedef bool(WINAPI* GetIsAttachedToPixFn)(void); 378 auto fn = (GetIsAttachedToPixFn)PixImpl::GetGpuCaptureFunctionPtr("GetIsAttachedToPix"); 379 if (fn == NULL) 380 { 381 OutputDebugStringW(L"WinPixEventRuntime error: Mismatched header/dll. Please ensure that pix3.h and WinPixGpuCapturer.dll match"); 382 return false; 383 } 384 385 return fn(); 386 } 387 388 __forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR fileName) 389 { 390 return ShellExecuteW(0, 0, fileName, 0, 0, SW_SHOW); 391 } 392 393 #else 394 __forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() 395 { 396 return nullptr; 397 } 398 __forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary() 399 { 400 return nullptr; 401 } 402 __forceinline HRESULT WINAPI PIXSetTargetWindow(HWND) 403 { 404 return E_NOTIMPL; 405 } 406 407 __forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR, UINT32) 408 { 409 return E_NOTIMPL; 410 } 411 extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD, _In_opt_ const PPIXCaptureParameters) 412 { 413 return E_NOTIMPL; 414 } 415 extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL) 416 { 417 return E_NOTIMPL; 418 } 419 __forceinline HRESULT WINAPI PIXForceD3D11On12() 420 { 421 return E_NOTIMPL; 422 } 423 __forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions) 424 { 425 return E_NOTIMPL; 426 } 427 __forceinline bool WINAPI PIXIsAttachedForGpuCapture() 428 { 429 return false; 430 } 431 __forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR) 432 { 433 return 0; 434 } 435 #endif // WINAPI_PARTITION 436 437 #endif // USE_PIX_SUPPORTED_ARCHITECTURE || USE_PIX 438 439 #endif //_PIX3_WIN_H_