duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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_