Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/winpixeventruntime/include/WinPixEventRuntime/pix3_win.h
4261 views
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_
440
441