diff --git a/dep/msvc/winpixeventruntime/WinPixEventRuntime.props b/dep/msvc/winpixeventruntime/WinPixEventRuntime.props
new file mode 100644
index 000000000..caea8f719
--- /dev/null
+++ b/dep/msvc/winpixeventruntime/WinPixEventRuntime.props
@@ -0,0 +1,39 @@
+
+
+
+ $(SolutionDir)bin\$(Platform)\
+ $(SolutionDir)dep\msvc\winpixeventruntime\
+
+
+
+ $(WinPixEventRuntimeDir)include;%(AdditionalIncludeDirectories)
+
+
+ $(WinPixEventRuntimeDir)lib64;%(AdditionalLibraryDirectories)
+ $(WinPixEventRuntimeDir)libarm64;%(AdditionalLibraryDirectories)
+ WinPixEventRuntime.lib;%(AdditionalDependencies)
+
+
+ $(WinPixEventRuntimeDir)lib64;%(AdditionalLibraryDirectories)
+ $(WinPixEventRuntimeDir)libarm64;%(AdditionalLibraryDirectories)
+ WinPixEventRuntime.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dep/msvc/winpixeventruntime/bin64/WinPixEventRuntime.dll b/dep/msvc/winpixeventruntime/bin64/WinPixEventRuntime.dll
new file mode 100644
index 000000000..0e2f75c51
Binary files /dev/null and b/dep/msvc/winpixeventruntime/bin64/WinPixEventRuntime.dll differ
diff --git a/dep/msvc/winpixeventruntime/binarm64/WinPixEventRuntime.dll b/dep/msvc/winpixeventruntime/binarm64/WinPixEventRuntime.dll
new file mode 100644
index 000000000..0e2f75c51
Binary files /dev/null and b/dep/msvc/winpixeventruntime/binarm64/WinPixEventRuntime.dll differ
diff --git a/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEvents.h b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEvents.h
new file mode 100644
index 000000000..ec5f2ed57
--- /dev/null
+++ b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEvents.h
@@ -0,0 +1,661 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+/*==========================================================================;
+ *
+ * Copyright (C) Microsoft Corporation. All Rights Reserved.
+ *
+ * File: PIXEvents.h
+ * Content: PIX include file
+ * Don't include this file directly - use pix3.h
+ *
+ ****************************************************************************/
+#pragma once
+
+#ifndef _PixEvents_H_
+#define _PixEvents_H_
+
+#ifndef _PIX3_H_
+# error Do not include this file directly - use pix3.h
+#endif
+
+#include "PIXEventsCommon.h"
+
+#if _MSC_VER < 1800
+# error This version of pix3.h is only supported on Visual Studio 2013 or higher
+#elif _MSC_VER < 1900
+# ifndef constexpr // Visual Studio 2013 doesn't support constexpr
+# define constexpr
+# define PIX3__DEFINED_CONSTEXPR
+# endif
+#endif
+
+// Xbox does not support CPU events for retail scenarios
+#if defined(USE_PIX) || !defined(PIX_XBOX)
+#define PIX_CONTEXT_EMIT_CPU_EVENTS
+#endif
+
+namespace PIXEventsDetail
+{
+ template
+ struct PIXEventTypeInferer
+ {
+ static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_VarArgs; }
+ static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_VarArgs; }
+ static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
+ static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
+
+ // Xbox and Windows store different types of events for context events.
+ // On Xbox these include a context argument, while on Windows they do
+ // not. It is important not to change the event types used on the
+ // Windows version as there are OS components (eg debug layer & DRED)
+ // that decode event structs.
+#ifdef PIX_XBOX
+ static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
+ static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
+#else
+ static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; }
+ static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; }
+#endif
+ };
+
+ template<>
+ struct PIXEventTypeInferer<>
+ {
+ static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_NoArgs; }
+ static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_NoArgs; }
+ static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
+ static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
+
+#ifdef PIX_XBOX
+ static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
+ static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
+#else
+ static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; }
+ static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; }
+#endif
+ };
+
+ inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
+ {
+ // nothing
+ UNREFERENCED_PARAMETER(destination);
+ UNREFERENCED_PARAMETER(limit);
+ }
+
+ template
+ void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args)
+ {
+ PIXCopyEventArgument(destination, limit, arg);
+ PIXCopyEventArguments(destination, limit, args...);
+ }
+
+ template
+ __declspec(noinline) void PIXBeginEventAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(false);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::Begin());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ template
+ void PIXBeginEvent(UINT64 color, STR formatString, ARGS... args)
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::Begin());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXBeginEventAllocate(threadInfo, color, formatString, args...);
+ }
+ }
+ }
+
+ template
+ __declspec(noinline) void PIXSetMarkerAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(false);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarker());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ template
+ void PIXSetMarker(UINT64 color, STR formatString, ARGS... args)
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarker());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXSetMarkerAllocate(threadInfo, color, formatString, args...);
+ }
+ }
+ }
+
+ template
+ __declspec(noinline) void PIXBeginEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(false);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::BeginOnContext());
+ *destination++ = color;
+
+#ifdef PIX_XBOX
+ UNREFERENCED_PARAMETER(context);
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+#else
+ PIXCopyEventArguments(destination, limit, context, formatString, args...);
+#endif
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ template
+ void PIXBeginEventOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args)
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::BeginOnContext());
+ *destination++ = color;
+
+#ifdef PIX_XBOX
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+#else
+ PIXCopyEventArguments(destination, limit, context, formatString, args...);
+#endif
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXBeginEventOnContextCpuAllocate(threadInfo, context, color, formatString, args...);
+ }
+ }
+ }
+
+ template
+ void PIXBeginEvent(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+ PIXBeginEventOnContextCpu(context, color, formatString, args...);
+#endif
+
+ // TODO: we've already encoded this once for the CPU event - figure out way to avoid doing it again
+ UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+ UINT64* destination = buffer;
+ UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+ *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuBeginOnContext());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+ *destination = 0ull;
+
+ PIXBeginGPUEventOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer)));
+ }
+
+ template
+ __declspec(noinline) void PIXSetMarkerOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(false);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarkerOnContext());
+ *destination++ = color;
+
+#ifdef PIX_XBOX
+ UNREFERENCED_PARAMETER(context);
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+#else
+ PIXCopyEventArguments(destination, limit, context, formatString, args...);
+#endif
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ template
+ void PIXSetMarkerOnContextCpu(void* context, UINT64 color, STR formatString, ARGS... args)
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEventTypeInferer::SetMarkerOnContext());
+ *destination++ = color;
+
+#ifdef PIX_XBOX
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+#else
+ PIXCopyEventArguments(destination, limit, context, formatString, args...);
+#endif
+
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXSetMarkerOnContextCpuAllocate(threadInfo, context, color, formatString, args...);
+ }
+ }
+ }
+
+ template
+ void PIXSetMarker(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
+ {
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+ PIXSetMarkerOnContextCpu(context, color, formatString, args...);
+#endif
+
+ UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+ UINT64* destination = buffer;
+ UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+ *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuSetMarkerOnContext());
+ *destination++ = color;
+
+ PIXCopyEventArguments(destination, limit, formatString, args...);
+ *destination = 0ull;
+
+ PIXSetGPUMarkerOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer)));
+ }
+
+ __declspec(noinline) inline void PIXEndEventAllocate(PIXEventsThreadInfo* threadInfo)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(true);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent);
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ inline void PIXEndEvent()
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent);
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXEndEventAllocate(threadInfo);
+ }
+ }
+ }
+
+ __declspec(noinline) inline void PIXEndEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context)
+ {
+#ifdef PIX_XBOX
+ UINT64 time = PIXEventsReplaceBlock(true);
+#else
+ UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
+#endif
+ if (!time)
+ return;
+
+ UINT64* destination = threadInfo->destination;
+ UINT64* limit = threadInfo->biasedLimit;
+
+ if (destination >= limit)
+ return;
+
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext);
+#ifdef PIX_XBOX
+ UNREFERENCED_PARAMETER(context);
+#else
+ PIXCopyEventArgument(destination, limit, context);
+#endif
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+
+ inline void PIXEndEventOnContextCpu(void* context)
+ {
+ PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+ UINT64* limit = threadInfo->biasedLimit;
+ if (limit != nullptr)
+ {
+ UINT64* destination = threadInfo->destination;
+ if (destination < limit)
+ {
+ limit += PIXEventsSafeFastCopySpaceQwords;
+ UINT64 time = PIXGetTimestampCounter();
+ *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent_OnContext);
+#ifndef PIX_XBOX
+ PIXCopyEventArgument(destination, limit, context);
+#endif
+ *destination = PIXEventsBlockEndMarker;
+ threadInfo->destination = destination;
+ }
+ else
+ {
+ PIXEndEventOnContextCpuAllocate(threadInfo, context);
+ }
+ }
+ }
+
+ template
+ void PIXEndEvent(CONTEXT* context)
+ {
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+ PIXEndEventOnContextCpu(context);
+#endif
+ PIXEndGPUEventOnContext(context);
+ }
+}
+
+#if defined(USE_PIX)
+
+template
+void PIXBeginEvent(UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template
+void PIXBeginEvent(UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template
+void PIXSetMarker(UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template
+void PIXSetMarker(UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template
+void PIXBeginEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template
+void PIXBeginEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template
+void PIXSetMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template
+void PIXSetMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+inline void PIXEndEvent()
+{
+ PIXEventsDetail::PIXEndEvent();
+}
+
+template
+void PIXEndEvent(CONTEXT* context)
+{
+ PIXEventsDetail::PIXEndEvent(context);
+}
+
+#else // USE_PIX_RETAIL
+
+inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {}
+inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {}
+inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {}
+inline void PIXEndEvent() {}
+inline void PIXEndEvent(void*) {}
+inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {}
+inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {}
+inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {}
+
+#endif // USE_PIX
+
+template
+void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template
+void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template
+void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template
+void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+ PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template
+void PIXEndRetailEvent(CONTEXT* context)
+{
+ PIXEventsDetail::PIXEndEvent(context);
+}
+
+template
+class PIXScopedEventObject
+{
+ CONTEXT* m_context;
+
+public:
+ template
+ PIXScopedEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+ : m_context(context)
+ {
+ PIXBeginEvent(m_context, color, formatString, args...);
+ }
+
+ template
+ PIXScopedEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+ : m_context(context)
+ {
+ PIXBeginEvent(m_context, color, formatString, args...);
+ }
+
+ ~PIXScopedEventObject()
+ {
+ PIXEndEvent(m_context);
+ }
+};
+
+template
+class PIXScopedRetailEventObject
+{
+ CONTEXT* m_context;
+
+public:
+ template
+ PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+ : m_context(context)
+ {
+ PIXBeginRetailEvent(m_context, color, formatString, args...);
+ }
+
+ template
+ PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+ : m_context(context)
+ {
+ PIXBeginRetailEvent(m_context, color, formatString, args...);
+ }
+
+ ~PIXScopedRetailEventObject()
+ {
+ PIXEndRetailEvent(m_context);
+ }
+};
+
+template<>
+class PIXScopedEventObject
+{
+public:
+ template
+ PIXScopedEventObject(UINT64 color, PCWSTR formatString, ARGS... args)
+ {
+ PIXBeginEvent(color, formatString, args...);
+ }
+
+ template
+ PIXScopedEventObject(UINT64 color, PCSTR formatString, ARGS... args)
+ {
+ PIXBeginEvent(color, formatString, args...);
+ }
+
+ ~PIXScopedEventObject()
+ {
+ PIXEndEvent();
+ }
+};
+
+#define PIXConcatenate(a, b) a ## b
+#define PIXGetScopedEventVariableName(a, b) PIXConcatenate(a, b)
+#define PIXScopedEvent(context, ...) PIXScopedEventObject::Type> PIXGetScopedEventVariableName(pixEvent, __LINE__)(context, __VA_ARGS__)
+
+#ifdef PIX3__DEFINED_CONSTEXPR
+#undef constexpr
+#undef PIX3__DEFINED_CONSTEXPR
+#endif
+
+#endif // _PIXEvents_H__
diff --git a/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEventsCommon.h b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEventsCommon.h
new file mode 100644
index 000000000..a9c21d97f
--- /dev/null
+++ b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/PIXEventsCommon.h
@@ -0,0 +1,605 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+/*==========================================================================;
+*
+* Copyright (C) Microsoft Corporation. All Rights Reserved.
+*
+* File: PIXEventsCommon.h
+* Content: PIX include file
+* Don't include this file directly - use pix3.h
+*
+****************************************************************************/
+#pragma once
+
+#ifndef _PIXEventsCommon_H_
+#define _PIXEventsCommon_H_
+
+#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
+#define PIX_XBOX
+#endif
+
+#include
+
+#if defined(_M_X64) || defined(_M_IX86)
+#include
+#endif
+
+//
+// The PIXBeginEvent and PIXSetMarker functions have an optimized path for
+// copying strings that work by copying 128-bit or 64-bits at a time. In some
+// circumstances this may result in PIX logging the remaining memory after the
+// null terminator.
+//
+// By default this optimization is enabled unless Address Sanitizer is enabled,
+// since this optimization can trigger a global-buffer-overflow when copying
+// string literals.
+//
+// The PIX_ENABLE_BLOCK_ARGUMENT_COPY controls whether or not this optimization
+// is enabled. Applications may also explicitly set this macro to 0 to disable
+// the optimization if necessary.
+//
+
+// Check for Address Sanitizer on either Clang or MSVC
+
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define PIX_ASAN_ENABLED
+#endif
+#elif defined(__SANITIZE_ADDRESS__)
+#define PIX_ASAN_ENABLED
+#endif
+
+#if defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY)
+// Previously set values override everything
+# define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 0
+#elif defined(PIX_ASAN_ENABLED)
+// Disable block argument copy when address sanitizer is enabled
+#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 0
+#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1
+#endif
+
+#if !defined(PIX_ENABLE_BLOCK_ARGUMENT_COPY)
+// Default to enabled.
+#define PIX_ENABLE_BLOCK_ARGUMENT_COPY 1
+#define PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET 1
+#endif
+
+struct PIXEventsBlockInfo;
+
+struct PIXEventsThreadInfo
+{
+ PIXEventsBlockInfo* block;
+ UINT64* biasedLimit;
+ UINT64* destination;
+};
+
+#ifdef PIX_XBOX
+extern "C" UINT64 WINAPI PIXEventsReplaceBlock(bool getEarliestTime) noexcept;
+#else
+extern "C" UINT64 WINAPI PIXEventsReplaceBlock(PIXEventsThreadInfo * threadInfo, bool getEarliestTime) noexcept;
+#endif
+
+enum PIXEventType
+{
+ PIXEvent_EndEvent = 0x000,
+ PIXEvent_BeginEvent_VarArgs = 0x001,
+ PIXEvent_BeginEvent_NoArgs = 0x002,
+ PIXEvent_SetMarker_VarArgs = 0x007,
+ PIXEvent_SetMarker_NoArgs = 0x008,
+
+ PIXEvent_EndEvent_OnContext = 0x010,
+ PIXEvent_BeginEvent_OnContext_VarArgs = 0x011,
+ PIXEvent_BeginEvent_OnContext_NoArgs = 0x012,
+ PIXEvent_SetMarker_OnContext_VarArgs = 0x017,
+ PIXEvent_SetMarker_OnContext_NoArgs = 0x018,
+};
+
+static const UINT64 PIXEventsReservedRecordSpaceQwords = 64;
+//this is used to make sure SSE string copy always will end 16-byte write in the current block
+//this way only a check if destination < limit can be performed, instead of destination < limit - 1
+//since both these are UINT64* and SSE writes in 16 byte chunks, 8 bytes are kept in reserve
+//so even if SSE overwrites 8 extra bytes, those will still belong to the correct block
+//on next iteration check destination will be greater than limit
+//this is used as well for fixed size UMD events and PIXEndEvent since these require less space
+//than other variable length user events and do not need big reserved space
+static const UINT64 PIXEventsReservedTailSpaceQwords = 2;
+static const UINT64 PIXEventsSafeFastCopySpaceQwords = PIXEventsReservedRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+static const UINT64 PIXEventsGraphicsRecordSpaceQwords = 64;
+
+//Bits 7-19 (13 bits)
+static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80;
+
+//Bits 10-19 (10 bits)
+static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00;
+static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF;
+static const UINT64 PIXEventsTypeBitShift = 10;
+
+//Bits 20-63 (44 bits)
+static const UINT64 PIXEventsTimestampReadMask = 0xFFFFFFFFFFF00000;
+static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
+static const UINT64 PIXEventsTimestampBitShift = 20;
+
+inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType)
+{
+ return ((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) |
+ (((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift);
+}
+
+//Bits 60-63 (4)
+static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F;
+static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000;
+static const UINT64 PIXEventsStringAlignmentBitShift = 60;
+
+//Bits 55-59 (5)
+static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F;
+static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000;
+static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55;
+
+//Bit 54
+static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001;
+static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000;
+static const UINT64 PIXEventsStringIsANSIBitShift = 54;
+
+//Bit 53
+static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001;
+static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000;
+static const UINT64 PIXEventsStringIsShortcutBitShift = 53;
+
+inline UINT64 PIXEncodeStringInfo(UINT64 alignment, UINT64 copyChunkSize, BOOL isANSI, BOOL isShortcut)
+{
+ return ((alignment & PIXEventsStringAlignmentWriteMask) << PIXEventsStringAlignmentBitShift) |
+ ((copyChunkSize & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) |
+ (((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift) |
+ (((UINT64)isShortcut & PIXEventsStringIsShortcutWriteMask) << PIXEventsStringIsShortcutBitShift);
+}
+
+template
+inline bool PIXIsPointerAligned(T* pointer)
+{
+ return !(((UINT64)pointer) & (alignment - 1));
+}
+
+// Generic template version slower because of the additional clear write
+template
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument)
+{
+ if (destination < limit)
+ {
+ *destination = 0ull;
+ *((T*)destination) = argument;
+ ++destination;
+ }
+}
+
+// int32 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
+{
+ if (destination < limit)
+ {
+ *reinterpret_cast(destination) = static_cast(argument);
+ ++destination;
+ }
+}
+
+// unsigned int32 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
+{
+ if (destination < limit)
+ {
+ *destination = static_cast(argument);
+ ++destination;
+ }
+}
+
+// int64 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
+{
+ if (destination < limit)
+ {
+ *reinterpret_cast(destination) = argument;
+ ++destination;
+ }
+}
+
+// unsigned int64 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument)
+{
+ if (destination < limit)
+ {
+ *destination = argument;
+ ++destination;
+ }
+}
+
+//floats must be cast to double during writing the data to be properly printed later when reading the data
+//this is needed because when float is passed to varargs function it's cast to double
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
+{
+ if (destination < limit)
+ {
+ *reinterpret_cast(destination) = static_cast(argument);
+ ++destination;
+ }
+}
+
+//char has to be cast to a longer signed integer type
+//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
+{
+ if (destination < limit)
+ {
+ *reinterpret_cast(destination) = static_cast(argument);
+ ++destination;
+ }
+}
+
+//unsigned char has to be cast to a longer unsigned integer type
+//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument)
+{
+ if (destination < limit)
+ {
+ *destination = static_cast(argument);
+ ++destination;
+ }
+}
+
+//bool has to be cast to an integer since it's not explicitly supported by string format routines
+//there's no format specifier for bool type, but it should work with integer format specifiers
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
+{
+ if (destination < limit)
+ {
+ *destination = static_cast(argument);
+ ++destination;
+ }
+}
+
+inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+ *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
+ while (destination < limit)
+ {
+ UINT64 c = static_cast(argument[0]);
+ if (!c)
+ {
+ *destination++ = 0;
+ return;
+ }
+ UINT64 x = c;
+ c = static_cast(argument[1]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 8;
+ c = static_cast(argument[2]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 16;
+ c = static_cast(argument[3]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 24;
+ c = static_cast(argument[4]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 32;
+ c = static_cast(argument[5]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 40;
+ c = static_cast(argument[6]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 48;
+ c = static_cast(argument[7]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 56;
+ *destination++ = x;
+ argument += 8;
+ }
+}
+
+inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+#if PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ if (PIXIsPointerAligned<8>(argument))
+ {
+ *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
+ UINT64* source = (UINT64*)argument;
+ while (destination < limit)
+ {
+ UINT64 qword = *source++;
+ *destination++ = qword;
+ //check if any of the characters is a terminating zero
+ if (!((qword & 0xFF00000000000000) &&
+ (qword & 0xFF000000000000) &&
+ (qword & 0xFF0000000000) &&
+ (qword & 0xFF00000000) &&
+ (qword & 0xFF000000) &&
+ (qword & 0xFF0000) &&
+ (qword & 0xFF00) &&
+ (qword & 0xFF)))
+ {
+ break;
+ }
+ }
+ }
+ else
+#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ {
+ PIXCopyEventArgumentSlowest(destination, limit, argument);
+ }
+}
+
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+ if (destination < limit)
+ {
+ if (argument != nullptr)
+ {
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ if (PIXIsPointerAligned<16>(argument))
+ {
+ *destination++ = PIXEncodeStringInfo(0, 16, TRUE, FALSE);
+ __m128i zero = _mm_setzero_si128();
+ if (PIXIsPointerAligned<16>(destination))
+ {
+ while (destination < limit)
+ {
+ __m128i mem = _mm_load_si128((__m128i*)argument);
+ _mm_store_si128((__m128i*)destination, mem);
+ //check if any of the characters is a terminating zero
+ __m128i res = _mm_cmpeq_epi8(mem, zero);
+ destination += 2;
+ if (_mm_movemask_epi8(res))
+ break;
+ argument += 16;
+ }
+ }
+ else
+ {
+ while (destination < limit)
+ {
+ __m128i mem = _mm_load_si128((__m128i*)argument);
+ _mm_storeu_si128((__m128i*)destination, mem);
+ //check if any of the characters is a terminating zero
+ __m128i res = _mm_cmpeq_epi8(mem, zero);
+ destination += 2;
+ if (_mm_movemask_epi8(res))
+ break;
+ argument += 16;
+ }
+ }
+ }
+ else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ {
+ PIXCopyEventArgumentSlow(destination, limit, argument);
+ }
+ }
+ else
+ {
+ *destination++ = 0ull;
+ }
+ }
+}
+
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
+{
+ PIXCopyEventArgument(destination, limit, (PCSTR)argument);
+}
+
+inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+ *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
+ while (destination < limit)
+ {
+ UINT64 c = static_cast(argument[0]);
+ if (!c)
+ {
+ *destination++ = 0;
+ return;
+ }
+ UINT64 x = c;
+ c = static_cast(argument[1]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 16;
+ c = static_cast(argument[2]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 32;
+ c = static_cast(argument[3]);
+ if (!c)
+ {
+ *destination++ = x;
+ return;
+ }
+ x |= c << 48;
+ *destination++ = x;
+ argument += 4;
+ }
+}
+
+inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+#if PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ if (PIXIsPointerAligned<8>(argument))
+ {
+ *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
+ UINT64* source = (UINT64*)argument;
+ while (destination < limit)
+ {
+ UINT64 qword = *source++;
+ *destination++ = qword;
+ //check if any of the characters is a terminating zero
+ //TODO: check if reversed condition is faster
+ if (!((qword & 0xFFFF000000000000) &&
+ (qword & 0xFFFF00000000) &&
+ (qword & 0xFFFF0000) &&
+ (qword & 0xFFFF)))
+ {
+ break;
+ }
+ }
+ }
+ else
+#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ {
+ PIXCopyEventArgumentSlowest(destination, limit, argument);
+ }
+}
+
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+ if (destination < limit)
+ {
+ if (argument != nullptr)
+ {
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ if (PIXIsPointerAligned<16>(argument))
+ {
+ *destination++ = PIXEncodeStringInfo(0, 16, FALSE, FALSE);
+ __m128i zero = _mm_setzero_si128();
+ if (PIXIsPointerAligned<16>(destination))
+ {
+ while (destination < limit)
+ {
+ __m128i mem = _mm_load_si128((__m128i*)argument);
+ _mm_store_si128((__m128i*)destination, mem);
+ //check if any of the characters is a terminating zero
+ __m128i res = _mm_cmpeq_epi16(mem, zero);
+ destination += 2;
+ if (_mm_movemask_epi8(res))
+ break;
+ argument += 8;
+ }
+ }
+ else
+ {
+ while (destination < limit)
+ {
+ __m128i mem = _mm_load_si128((__m128i*)argument);
+ _mm_storeu_si128((__m128i*)destination, mem);
+ //check if any of the characters is a terminating zero
+ __m128i res = _mm_cmpeq_epi16(mem, zero);
+ destination += 2;
+ if (_mm_movemask_epi8(res))
+ break;
+ argument += 8;
+ }
+ }
+ }
+ else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+ {
+ PIXCopyEventArgumentSlow(destination, limit, argument);
+ }
+ }
+ else
+ {
+ *destination++ = 0ull;
+ }
+ }
+}
+
+template<>
+inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument)
+{
+ PIXCopyEventArgument(destination, limit, (PCWSTR)argument);
+};
+
+#if defined(__d3d12_x_h__) || defined(__d3d12_xs_h__) || defined(__d3d12_h__)
+
+inline void PIXSetGPUMarkerOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size)
+{
+ commandList->SetMarker(D3D12_EVENT_METADATA, data, size);
+}
+
+inline void PIXSetGPUMarkerOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size)
+{
+ commandQueue->SetMarker(D3D12_EVENT_METADATA, data, size);
+}
+
+inline void PIXBeginGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size)
+{
+ commandList->BeginEvent(D3D12_EVENT_METADATA, data, size);
+}
+
+inline void PIXBeginGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size)
+{
+ commandQueue->BeginEvent(D3D12_EVENT_METADATA, data, size);
+}
+
+inline void PIXEndGPUEventOnContext(_In_ ID3D12GraphicsCommandList* commandList)
+{
+ commandList->EndEvent();
+}
+
+inline void PIXEndGPUEventOnContext(_In_ ID3D12CommandQueue* commandQueue)
+{
+ commandQueue->EndEvent();
+}
+
+#endif //__d3d12_h__
+
+template struct PIXInferScopedEventType { typedef T Type; };
+template struct PIXInferScopedEventType { typedef T Type; };
+template struct PIXInferScopedEventType { typedef T Type; };
+template struct PIXInferScopedEventType { typedef T Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+template<> struct PIXInferScopedEventType { typedef void Type; };
+
+
+#if PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET
+#undef PIX_ENABLE_BLOCK_ARGUMENT_COPY
+#endif
+
+#undef PIX_ENABLE_BLOCK_ARGUMENT_COPY_SET
+
+#endif //_PIXEventsCommon_H_
diff --git a/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3.h b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3.h
new file mode 100644
index 000000000..9007765e4
--- /dev/null
+++ b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3.h
@@ -0,0 +1,175 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+/*==========================================================================;
+ *
+ * Copyright (C) Microsoft Corporation. All Rights Reserved.
+ *
+ * File: pix3.h
+ * Content: PIX include file
+ *
+ ****************************************************************************/
+#pragma once
+
+#ifndef _PIX3_H_
+#define _PIX3_H_
+
+#include
+
+#ifndef __cplusplus
+#error "Only C++ files can include pix3.h. C is not supported."
+#endif
+
+#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE)
+#if defined(_M_X64) || defined(USE_PIX_ON_ALL_ARCHITECTURES) || defined(_M_ARM64)
+#define USE_PIX_SUPPORTED_ARCHITECTURE
+#endif
+#endif
+
+#if !defined(USE_PIX)
+#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(_DEBUG) || DBG || defined(PROFILE) || defined(PROFILE_BUILD)) && !defined(_PREFAST_)
+#define USE_PIX
+#endif
+#endif
+
+#if defined(USE_PIX) && !defined(USE_PIX_SUPPORTED_ARCHITECTURE)
+#pragma message("Warning: Pix markers are only supported on AMD64 and ARM64")
+#endif
+
+
+// These flags are used by both PIXBeginCapture and PIXGetCaptureState
+#define PIX_CAPTURE_TIMING (1 << 0)
+#define PIX_CAPTURE_GPU (1 << 1)
+#define PIX_CAPTURE_FUNCTION_SUMMARY (1 << 2)
+#define PIX_CAPTURE_FUNCTION_DETAILS (1 << 3)
+#define PIX_CAPTURE_CALLGRAPH (1 << 4)
+#define PIX_CAPTURE_INSTRUCTION_TRACE (1 << 5)
+#define PIX_CAPTURE_SYSTEM_MONITOR_COUNTERS (1 << 6)
+#define PIX_CAPTURE_VIDEO (1 << 7)
+#define PIX_CAPTURE_AUDIO (1 << 8)
+#define PIX_CAPTURE_RESERVED (1 << 15)
+
+union PIXCaptureParameters
+{
+ enum PIXCaptureStorage
+ {
+ Memory = 0,
+ };
+
+ struct GpuCaptureParameters
+ {
+ PCWSTR FileName;
+ } GpuCaptureParameters;
+
+ struct TimingCaptureParameters
+ {
+ PCWSTR FileName;
+ UINT32 MaximumToolingMemorySizeMb;
+ PIXCaptureStorage CaptureStorage;
+
+ BOOL CaptureGpuTiming;
+
+ BOOL CaptureCallstacks;
+ BOOL CaptureCpuSamples;
+ UINT32 CpuSamplesPerSecond;
+
+ BOOL CaptureFileIO;
+
+ BOOL CaptureVirtualAllocEvents;
+ BOOL CaptureHeapAllocEvents;
+ BOOL CaptureXMemEvents; // Xbox only
+ BOOL CapturePixMemEvents; // Xbox only
+ } TimingCaptureParameters;
+};
+
+typedef PIXCaptureParameters* PPIXCaptureParameters;
+
+#if defined(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
+#include "pix3_xbox.h"
+#else
+#include "pix3_win.h"
+#endif
+
+#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && (defined(USE_PIX) || defined(USE_PIX_RETAIL))
+
+#define PIX_EVENTS_ARE_TURNED_ON
+
+#include "PIXEventsCommon.h"
+#include "PIXEvents.h"
+
+#ifdef USE_PIX
+// Starts a programmatically controlled capture.
+// captureFlags uses the PIX_CAPTURE_* family of flags to specify the type of capture to take
+extern "C" HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters);
+inline HRESULT PIXBeginCapture(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) { return PIXBeginCapture2(captureFlags, captureParameters); }
+
+// Stops a programmatically controlled capture
+// If discard == TRUE, the captured data is discarded
+// If discard == FALSE, the captured data is saved
+// discard parameter is not supported on Windows
+extern "C" HRESULT WINAPI PIXEndCapture(BOOL discard);
+
+extern "C" DWORD WINAPI PIXGetCaptureState();
+
+extern "C" void WINAPI PIXReportCounter(_In_ PCWSTR name, float value);
+
+#endif // USE_PIX
+
+#endif // (USE_PIX_SUPPORTED_ARCHITECTURE) && (USE_PIX || USE_PIX_RETAIL)
+
+#if !defined(USE_PIX_SUPPORTED_ARCHITECTURE) || !defined(USE_PIX)
+
+// Eliminate these APIs when not using PIX
+inline HRESULT PIXBeginCapture2(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; }
+inline HRESULT PIXBeginCapture(DWORD, _In_opt_ const PIXCaptureParameters*) { return S_OK; }
+inline HRESULT PIXEndCapture(BOOL) { return S_OK; }
+inline HRESULT PIXGpuCaptureNextFrames(PCWSTR, UINT32) { return S_OK; }
+inline HRESULT PIXSetTargetWindow(HWND) { return S_OK; }
+inline HRESULT PIXForceD3D11On12() { return S_OK; }
+inline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions) { return S_OK; }
+inline bool WINAPI PIXIsAttachedForGpuCapture() { return false; }
+inline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR) { return 0; }
+inline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() { return nullptr; }
+inline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary() { return nullptr; }
+inline DWORD PIXGetCaptureState() { return 0; }
+inline void PIXReportCounter(_In_ PCWSTR, float) {}
+inline void PIXNotifyWakeFromFenceSignal(_In_ HANDLE) {}
+
+#if !defined(USE_PIX_RETAIL)
+
+inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {}
+inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {}
+inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {}
+inline void PIXEndEvent() {}
+inline void PIXEndEvent(void*) {}
+inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {}
+inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {}
+inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {}
+inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXBeginRetailEvent(void*, UINT64, _In_ PCWSTR, ...) {}
+inline void PIXEndRetailEvent(void*) {}
+inline void PIXSetRetailMarker(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXSetRetailMarker(void*, UINT64, _In_ PCWSTR, ...) {}
+inline void PIXScopedEvent(UINT64, _In_ PCSTR, ...) {}
+inline void PIXScopedEvent(UINT64, _In_ PCWSTR, ...) {}
+inline void PIXScopedEvent(void*, UINT64, _In_ PCSTR, ...) {}
+inline void PIXScopedEvent(void*, UINT64, _In_ PCWSTR, ...) {}
+
+#endif // !USE_PIX_RETAIL
+
+// don't show warnings about expressions with no effect
+#pragma warning(disable:4548)
+#pragma warning(disable:4555)
+
+#endif // !USE_PIX_SUPPORTED_ARCHITECTURE || !USE_PIX
+
+// Use these functions to specify colors to pass as metadata to a PIX event/marker API.
+// Use PIX_COLOR() to specify a particular color for an event.
+// Or, use PIX_COLOR_INDEX() to specify a set of unique event categories, and let PIX choose
+// the colors to represent each category.
+inline UINT PIX_COLOR(BYTE r, BYTE g, BYTE b) { return 0xff000000 | (r << 16) | (g << 8) | b; }
+inline UINT PIX_COLOR_INDEX(BYTE i) { return i; }
+const UINT PIX_COLOR_DEFAULT = PIX_COLOR_INDEX(0);
+
+#endif // _PIX3_H_
diff --git a/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3_win.h b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3_win.h
new file mode 100644
index 000000000..2c7d0a537
--- /dev/null
+++ b/dep/msvc/winpixeventruntime/include/WinPixEventRuntime/pix3_win.h
@@ -0,0 +1,439 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+
+/*==========================================================================;
+ *
+ * Copyright (C) Microsoft Corporation. All Rights Reserved.
+ *
+ * File: PIX3_win.h
+ * Content: PIX include file
+ * Don't include this file directly - use pix3.h
+ *
+ ****************************************************************************/
+
+#pragma once
+
+#ifndef _PIX3_H_
+#error Don't include this file directly - use pix3.h
+#endif
+
+#ifndef _PIX3_WIN_H_
+#define _PIX3_WIN_H_
+
+// PIXEventsThreadInfo is defined in PIXEventsCommon.h
+struct PIXEventsThreadInfo;
+
+extern "C" PIXEventsThreadInfo* WINAPI PIXGetThreadInfo() noexcept;
+
+#if defined(USE_PIX) && defined(USE_PIX_SUPPORTED_ARCHITECTURE)
+// Notifies PIX that an event handle was set as a result of a D3D12 fence being signaled.
+// The event specified must have the same handle value as the handle
+// used in ID3D12Fence::SetEventOnCompletion.
+extern "C" void WINAPI PIXNotifyWakeFromFenceSignal(_In_ HANDLE event);
+
+// Notifies PIX that a block of memory was allocated
+extern "C" void WINAPI PIXRecordMemoryAllocationEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata);
+
+// Notifies PIX that a block of memory was freed
+extern "C" void WINAPI PIXRecordMemoryFreeEvent(USHORT allocatorId, void* baseAddress, size_t size, UINT64 metadata);
+
+#else
+
+// Eliminate these APIs when not using PIX
+inline void PIXRecordMemoryAllocationEvent(USHORT, void*, size_t, UINT64) {}
+inline void PIXRecordMemoryFreeEvent(USHORT, void*, size_t, UINT64) {}
+
+#endif
+
+// The following defines denote the different metadata values that have been used
+// by tools to denote how to parse pix marker event data. The first two values
+// are legacy values.
+#define WINPIX_EVENT_UNICODE_VERSION 0
+#define WINPIX_EVENT_ANSI_VERSION 1
+#define WINPIX_EVENT_PIX3BLOB_VERSION 2
+
+#define D3D12_EVENT_METADATA WINPIX_EVENT_PIX3BLOB_VERSION
+
+__forceinline UINT64 PIXGetTimestampCounter()
+{
+ LARGE_INTEGER time = {};
+ QueryPerformanceCounter(&time);
+ return static_cast(time.QuadPart);
+}
+
+enum PIXHUDOptions
+{
+ PIX_HUD_SHOW_ON_ALL_WINDOWS = 0x1,
+ PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY = 0x2,
+ PIX_HUD_SHOW_ON_NO_WINDOWS = 0x4
+};
+DEFINE_ENUM_FLAG_OPERATORS(PIXHUDOptions);
+
+#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && defined(USE_PIX)
+
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
+
+#include
+#include
+#include
+#include
+
+#define PIXERRORCHECK(value) do { \
+ if (FAILED(value)) \
+ return nullptr; \
+ } while(0)
+
+namespace PixImpl
+{
+#ifndef PIX3_WIN_UNIT_TEST
+
+ __forceinline BOOL GetModuleHandleExW(
+ DWORD dwFlags,
+ LPCWSTR lpModuleName,
+ HMODULE* phModule)
+ {
+ return ::GetModuleHandleExW(dwFlags, lpModuleName, phModule);
+ }
+
+ __forceinline HRESULT SHGetKnownFolderPath(
+ REFKNOWNFOLDERID rfid,
+ DWORD dwFlags,
+ HANDLE hToken,
+ PWSTR* ppszPath)
+ {
+ return ::SHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath);
+ }
+
+ __forceinline void CoTaskMemFree(LPVOID pv)
+ {
+ return ::CoTaskMemFree(pv);
+ }
+
+ __forceinline HANDLE FindFirstFileW(
+ LPCWSTR lpFileName,
+ LPWIN32_FIND_DATAW lpFindFileData)
+ {
+ return ::FindFirstFileW(lpFileName, lpFindFileData);
+ }
+
+ __forceinline DWORD GetFileAttributesW(LPCWSTR lpFileName)
+ {
+ return ::GetFileAttributesW(lpFileName);
+ }
+
+ __forceinline BOOL FindNextFileW(
+ HANDLE hFindFile,
+ LPWIN32_FIND_DATAW lpFindFileData)
+ {
+ return ::FindNextFileW(hFindFile, lpFindFileData);
+ }
+
+ __forceinline BOOL FindClose(HANDLE hFindFile)
+ {
+ return ::FindClose(hFindFile);
+ }
+
+ __forceinline HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, DWORD flags)
+ {
+ return ::LoadLibraryExW(lpLibFileName, NULL, flags);
+ }
+
+#endif // !PIX3_WIN_UNIT_TESTS
+
+ __forceinline void * GetGpuCaptureFunctionPtr(LPCSTR fnName) noexcept
+ {
+ HMODULE module = GetModuleHandleW(L"WinPixGpuCapturer.dll");
+ if (module == NULL)
+ {
+ return nullptr;
+ }
+
+ auto fn = (void*)GetProcAddress(module, fnName);
+ if (fn == nullptr)
+ {
+ return nullptr;
+ }
+
+ return fn;
+ }
+
+ __forceinline void* GetTimingCaptureFunctionPtr(LPCSTR fnName) noexcept
+ {
+ HMODULE module = GetModuleHandleW(L"WinPixTimingCapturer.dll");
+ if (module == NULL)
+ {
+ return nullptr;
+ }
+
+ auto fn = (void*)GetProcAddress(module, fnName);
+ if (fn == nullptr)
+ {
+ return nullptr;
+ }
+
+ return fn;
+ }
+
+ __forceinline HMODULE PIXLoadLatestCapturerLibrary(wchar_t const* capturerDllName, DWORD flags)
+ {
+ HMODULE libHandle{};
+
+ if (PixImpl::GetModuleHandleExW(0, capturerDllName, &libHandle))
+ {
+ return libHandle;
+ }
+
+ LPWSTR programFilesPath = nullptr;
+ if (FAILED(PixImpl::SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath)))
+ {
+ PixImpl::CoTaskMemFree(programFilesPath);
+ return nullptr;
+ }
+
+ wchar_t pixSearchPath[MAX_PATH];
+
+ if (FAILED(StringCchCopyW(pixSearchPath, MAX_PATH, programFilesPath)))
+ {
+ PixImpl::CoTaskMemFree(programFilesPath);
+ return nullptr;
+ }
+ PixImpl::CoTaskMemFree(programFilesPath);
+
+ PIXERRORCHECK(StringCchCatW(pixSearchPath, MAX_PATH, L"\\Microsoft PIX\\*"));
+
+ WIN32_FIND_DATAW findData;
+ bool foundPixInstallation = false;
+ wchar_t newestVersionFound[MAX_PATH];
+ wchar_t output[MAX_PATH];
+ wchar_t possibleOutput[MAX_PATH];
+
+ HANDLE hFind = PixImpl::FindFirstFileW(pixSearchPath, &findData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) &&
+ (findData.cFileName[0] != '.'))
+ {
+ if (!foundPixInstallation || wcscmp(newestVersionFound, findData.cFileName) <= 0)
+ {
+ // length - 1 to get rid of the wildcard character in the search path
+ PIXERRORCHECK(StringCchCopyNW(possibleOutput, MAX_PATH, pixSearchPath, wcslen(pixSearchPath) - 1));
+ PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, findData.cFileName));
+ PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, L"\\"));
+ PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, capturerDllName));
+
+ DWORD result = PixImpl::GetFileAttributesW(possibleOutput);
+
+ if (result != INVALID_FILE_ATTRIBUTES && !(result & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ foundPixInstallation = true;
+ PIXERRORCHECK(StringCchCopyW(newestVersionFound, _countof(newestVersionFound), findData.cFileName));
+ PIXERRORCHECK(StringCchCopyW(output, _countof(possibleOutput), possibleOutput));
+ }
+ }
+ }
+ } while (PixImpl::FindNextFileW(hFind, &findData) != 0);
+ }
+
+ PixImpl::FindClose(hFind);
+
+ if (!foundPixInstallation)
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return nullptr;
+ }
+
+ return PixImpl::LoadLibraryExW(output, flags);
+ }
+}
+
+#undef PIXERRORCHECK
+
+__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary()
+{
+ return PixImpl::PIXLoadLatestCapturerLibrary(
+ L"WinPixGpuCapturer.dll",
+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
+}
+
+__forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary()
+{
+ return PixImpl::PIXLoadLatestCapturerLibrary(
+ L"WinPixTimingCapturer.dll",
+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+}
+
+__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND hwnd)
+{
+ typedef void(WINAPI* SetGlobalTargetWindowFn)(HWND);
+
+ auto fn = (SetGlobalTargetWindowFn)PixImpl::GetGpuCaptureFunctionPtr("SetGlobalTargetWindow");
+ if (fn == nullptr)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ fn(hwnd);
+ return S_OK;
+}
+
+__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames)
+{
+ typedef HRESULT(WINAPI* CaptureNextFrameFn)(PCWSTR, UINT32);
+
+ auto fn = (CaptureNextFrameFn)PixImpl::GetGpuCaptureFunctionPtr("CaptureNextFrame");
+ if (fn == nullptr)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return fn(fileName, numFrames);
+}
+
+extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters)
+{
+ if (captureFlags == PIX_CAPTURE_GPU)
+ {
+ typedef HRESULT(WINAPI* BeginProgrammaticGpuCaptureFn)(const PPIXCaptureParameters);
+
+ auto fn = (BeginProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("BeginProgrammaticGpuCapture");
+ if (fn == nullptr)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return fn(captureParameters);
+ }
+ else if (captureFlags == PIX_CAPTURE_TIMING)
+ {
+ typedef HRESULT(WINAPI* BeginProgrammaticTimingCaptureFn)(void const*, UINT64);
+
+ auto fn = (BeginProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("BeginProgrammaticTimingCapture");
+ if (fn == nullptr)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return fn(&captureParameters->TimingCaptureParameters, sizeof(captureParameters->TimingCaptureParameters));
+ }
+ else
+ {
+ return E_NOTIMPL;
+ }
+}
+
+extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL discard)
+{
+ UNREFERENCED_PARAMETER(discard);
+
+ // We can't tell if the user wants to end a GPU Capture or a Timing Capture.
+ // The user shouldn't have both WinPixGpuCapturer and WinPixTimingCapturer loaded in the process though,
+ // so we can just look for one of them and call it.
+ typedef HRESULT(WINAPI* EndProgrammaticGpuCaptureFn)(void);
+ auto gpuFn = (EndProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("EndProgrammaticGpuCapture");
+ if (gpuFn != NULL)
+ {
+ return gpuFn();
+ }
+
+ typedef HRESULT(WINAPI* EndProgrammaticTimingCaptureFn)(BOOL);
+ auto timingFn = (EndProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("EndProgrammaticTimingCapture");
+ if (timingFn != NULL)
+ {
+ return timingFn(discard);
+ }
+
+ return HRESULT_FROM_WIN32(GetLastError());
+}
+
+__forceinline HRESULT WINAPI PIXForceD3D11On12()
+{
+ typedef HRESULT (WINAPI* ForceD3D11On12Fn)(void);
+
+ auto fn = (ForceD3D11On12Fn)PixImpl::GetGpuCaptureFunctionPtr("ForceD3D11On12");
+ if (fn == NULL)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return fn();
+}
+
+__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions hudOptions)
+{
+ typedef HRESULT(WINAPI* SetHUDOptionsFn)(PIXHUDOptions);
+
+ auto fn = (SetHUDOptionsFn)PixImpl::GetGpuCaptureFunctionPtr("SetHUDOptions");
+ if (fn == NULL)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return fn(hudOptions);
+}
+
+__forceinline bool WINAPI PIXIsAttachedForGpuCapture()
+{
+ typedef bool(WINAPI* GetIsAttachedToPixFn)(void);
+ auto fn = (GetIsAttachedToPixFn)PixImpl::GetGpuCaptureFunctionPtr("GetIsAttachedToPix");
+ if (fn == NULL)
+ {
+ OutputDebugStringW(L"WinPixEventRuntime error: Mismatched header/dll. Please ensure that pix3.h and WinPixGpuCapturer.dll match");
+ return false;
+ }
+
+ return fn();
+}
+
+__forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR fileName)
+{
+ return ShellExecuteW(0, 0, fileName, 0, 0, SW_SHOW);
+}
+
+#else
+__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary()
+{
+ return nullptr;
+}
+__forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary()
+{
+ return nullptr;
+}
+__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND)
+{
+ return E_NOTIMPL;
+}
+
+__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR, UINT32)
+{
+ return E_NOTIMPL;
+}
+extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD, _In_opt_ const PPIXCaptureParameters)
+{
+ return E_NOTIMPL;
+}
+extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL)
+{
+ return E_NOTIMPL;
+}
+__forceinline HRESULT WINAPI PIXForceD3D11On12()
+{
+ return E_NOTIMPL;
+}
+__forceinline HRESULT WINAPI PIXSetHUDOptions(PIXHUDOptions)
+{
+ return E_NOTIMPL;
+}
+__forceinline bool WINAPI PIXIsAttachedForGpuCapture()
+{
+ return false;
+}
+__forceinline HINSTANCE WINAPI PIXOpenCaptureInUI(PCWSTR)
+{
+ return 0;
+}
+#endif // WINAPI_PARTITION
+
+#endif // USE_PIX_SUPPORTED_ARCHITECTURE || USE_PIX
+
+#endif //_PIX3_WIN_H_
diff --git a/dep/msvc/winpixeventruntime/lib64/WinPixEventRuntime.lib b/dep/msvc/winpixeventruntime/lib64/WinPixEventRuntime.lib
new file mode 100644
index 000000000..d5628599e
Binary files /dev/null and b/dep/msvc/winpixeventruntime/lib64/WinPixEventRuntime.lib differ
diff --git a/dep/msvc/winpixeventruntime/libarm64/WinPixEventRuntime.lib b/dep/msvc/winpixeventruntime/libarm64/WinPixEventRuntime.lib
new file mode 100644
index 000000000..fc17386b4
Binary files /dev/null and b/dep/msvc/winpixeventruntime/libarm64/WinPixEventRuntime.lib differ