Browse Source

D3D: Add debug markers

Panagiotis Christopoulos Charitos 1 year ago
parent
commit
4e2bb0c9b6

+ 13 - 6
AnKi/Gr/CMakeLists.txt

@@ -48,7 +48,12 @@ elseif(DIRECTX)
 	set(backend_sources  ${backend_sources} ${dxsources})
 	set(backend_sources  ${backend_sources} ${dxsources})
 	set(backend_headers ${backend_headers} ${dxheaders})
 	set(backend_headers ${backend_headers} ${dxheaders})
 
 
-	set(extra_libs ${extra_libs} d3d12 dxgi dxguid) # dxguid for some debug layer stuff
+	find_library(PIX_LIB WinPixEventRuntime HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/Pix/bin/x64")
+
+	set(extra_libs ${extra_libs} d3d12 dxgi dxguid ${PIX_LIB}) # dxguid for some debug layer stuff
+
+	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/include")
+	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/Pix/include/WinPixEventRuntime")
 endif()
 endif()
 
 
 # Have 2 libraries. The AnKiGrCommon is the bare minimum for the AnKiShaderCompiler to work. Don't have
 # Have 2 libraries. The AnKiGrCommon is the bare minimum for the AnKiShaderCompiler to work. Don't have
@@ -62,13 +67,14 @@ if(ANKI_DLSS)
 	set(extra_libs ${extra_libs} AnKiNgx)
 	set(extra_libs ${extra_libs} AnKiNgx)
 endif()
 endif()
 
 
-# Add Agility SDK includes
+add_library(AnKiGr ${backend_sources} ${backend_headers})
+
+set(COMPILE_DEFS "-DANKI_SOURCE_FILE")
 if(DIRECTX)
 if(DIRECTX)
-	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/include")
+	set(COMPILE_DEFS ${COMPILE_DEFS} "-DUSE_PIX")	
 endif()
 endif()
+target_compile_definitions(AnKiGr PRIVATE ${COMPILE_DEFS})
 
 
-add_library(AnKiGr ${backend_sources} ${backend_headers})
-target_compile_definitions(AnKiGr PRIVATE -DANKI_SOURCE_FILE)
 target_link_libraries(AnKiGr AnKiCore AnKiSpirvCross AnKiGrCommon ${extra_libs})
 target_link_libraries(AnKiGr AnKiCore AnKiSpirvCross AnKiGrCommon ${extra_libs})
 
 
 # Copy DLSS files to Binaries
 # Copy DLSS files to Binaries
@@ -98,8 +104,9 @@ endif()
 if(DIRECTX)
 if(DIRECTX)
 	file(GLOB FILES_TO_COPY "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/bin/x64/*.dll")
 	file(GLOB FILES_TO_COPY "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/bin/x64/*.dll")
 	file(GLOB FILES_TO_COPY2 "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/bin/x64/*.pdb")
 	file(GLOB FILES_TO_COPY2 "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/AgilitySdk/bin/x64/*.pdb")
+	file(GLOB FILES_TO_COPY3 "${CMAKE_CURRENT_SOURCE_DIR}/../../ThirdParty/Pix/bin/x64/*.dll")
 
 
-	list(APPEND FILES_TO_COPY ${FILES_TO_COPY2})
+	list(APPEND FILES_TO_COPY ${FILES_TO_COPY2} ${FILES_TO_COPY3})
 
 
 	foreach(FILE_TO_COPY IN LISTS FILES_TO_COPY)
 	foreach(FILE_TO_COPY IN LISTS FILES_TO_COPY)
 		add_custom_command(TARGET AnKiGr POST_BUILD
 		add_custom_command(TARGET AnKiGr POST_BUILD

+ 17 - 3
AnKi/Gr/D3D/D3DCommandBuffer.cpp

@@ -772,7 +772,6 @@ Bool CommandBuffer::isEmpty() const
 void CommandBuffer::setPushConstants(const void* data, U32 dataSize)
 void CommandBuffer::setPushConstants(const void* data, U32 dataSize)
 {
 {
 	ANKI_D3D_SELF(CommandBufferImpl);
 	ANKI_D3D_SELF(CommandBufferImpl);
-
 	self.m_descriptors.setRootConstants(data, dataSize);
 	self.m_descriptors.setRootConstants(data, dataSize);
 }
 }
 
 
@@ -788,12 +787,25 @@ void CommandBuffer::setLineWidth(F32 width)
 
 
 void CommandBuffer::pushDebugMarker(CString name, Vec3 color)
 void CommandBuffer::pushDebugMarker(CString name, Vec3 color)
 {
 {
-	ANKI_ASSERT(!"TODO");
+	ANKI_D3D_SELF(CommandBufferImpl);
+
+	if(self.m_debugMarkersEnabled)
+	{
+		const UVec3 coloru(color * 255.0f);
+		const U64 val = (U64(coloru.x()) << 48) | (U64(coloru.x()) << 32) | (U64(coloru.x()) << 16);
+
+		PIXBeginEvent(self.m_cmdList, val, "%s", name.cstr());
+	}
 }
 }
 
 
 void CommandBuffer::popDebugMarker()
 void CommandBuffer::popDebugMarker()
 {
 {
-	ANKI_ASSERT(!"TODO");
+	ANKI_D3D_SELF(CommandBufferImpl);
+
+	if(self.m_debugMarkersEnabled)
+	{
+		PIXEndEvent(self.m_cmdList);
+	}
 }
 }
 
 
 CommandBufferImpl::~CommandBufferImpl()
 CommandBufferImpl::~CommandBufferImpl()
@@ -809,6 +821,8 @@ Error CommandBufferImpl::init(const CommandBufferInitInfo& init)
 
 
 	m_descriptors.init(m_fastPool);
 	m_descriptors.init(m_fastPool);
 
 
+	m_debugMarkersEnabled = g_debugMarkersCVar.get();
+
 	return Error::kNone;
 	return Error::kNone;
 }
 }
 
 

+ 1 - 0
AnKi/Gr/D3D/D3DCommandBuffer.h

@@ -52,6 +52,7 @@ private:
 	DynamicArray<QueryHandle, MemoryPoolPtrWrapper<StackMemoryPool>> m_timestampQueries;
 	DynamicArray<QueryHandle, MemoryPoolPtrWrapper<StackMemoryPool>> m_timestampQueries;
 
 
 	Bool m_descriptorHeapsBound = false;
 	Bool m_descriptorHeapsBound = false;
+	Bool m_debugMarkersEnabled = false;
 
 
 	void commandCommon()
 	void commandCommon()
 	{
 	{

+ 1 - 0
AnKi/Gr/D3D/D3DCommon.h

@@ -25,6 +25,7 @@
 #include <D3Dcompiler.h>
 #include <D3Dcompiler.h>
 #include <DirectXMath.h>
 #include <DirectXMath.h>
 #include <wrl.h>
 #include <wrl.h>
+#include <pix3.h>
 #include <AnKi/Util/CleanupWindows.h>
 #include <AnKi/Util/CleanupWindows.h>
 
 
 using Microsoft::WRL::ComPtr;
 using Microsoft::WRL::ComPtr;

+ 4 - 0
Tests/Gr/Gr.cpp

@@ -748,6 +748,8 @@ float4 main(VertOut i) : SV_TARGET0
 												TextureUsageBit::kFramebufferWrite};
 												TextureUsageBit::kFramebufferWrite};
 			cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
 			cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
 
 
+			cmdb->pushDebugMarker("AnKi", Vec3(1.0f, 0.0f, 0.0f));
+
 			cmdb->beginRenderPass({TextureView(presentTex.get(), TextureSubresourceDescriptor::firstSurface())});
 			cmdb->beginRenderPass({TextureView(presentTex.get(), TextureSubresourceDescriptor::firstSurface())});
 
 
 			// Set uniforms
 			// Set uniforms
@@ -777,6 +779,8 @@ float4 main(VertOut i) : SV_TARGET0
 												 TextureUsageBit::kFramebufferWrite, TextureUsageBit::kPresent};
 												 TextureUsageBit::kFramebufferWrite, TextureUsageBit::kPresent};
 			cmdb->setPipelineBarrier({&barrier2, 1}, {}, {});
 			cmdb->setPipelineBarrier({&barrier2, 1}, {}, {});
 
 
+			cmdb->popDebugMarker();
+
 			cmdb->endRecording();
 			cmdb->endRecording();
 			GrManager::getSingleton().submit(cmdb.get());
 			GrManager::getSingleton().submit(cmdb.get());
 
 

+ 1578 - 0
ThirdParty/Pix/Include/WinPixEventRuntime/PIXEvents.h

@@ -0,0 +1,1578 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// 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
+{
+    inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
+    {
+        // nothing
+        UNREFERENCED_PARAMETER(destination);
+        UNREFERENCED_PARAMETER(limit);
+    }
+
+    template<typename ARG, typename... ARGS>
+    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<typename ARG, typename... ARGS>
+    void PIXCopyStringArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args)
+    {
+        PIXCopyStringArgument(destination, limit, arg);
+        PIXCopyEventArguments(destination, limit, args...);
+    }
+
+    template<typename ARG, typename... ARGS>
+    void PIXCopyStringArgumentsWithContext(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, void* context, ARG const& arg, ARGS const&... args)
+    {
+#ifdef PIX_XBOX
+        UNREFERENCED_PARAMETER(context);
+        PIXCopyStringArgument(destination, limit, arg);
+        PIXCopyEventArguments(destination, limit, args...);
+#else
+        PIXCopyEventArgument(destination, limit, context);
+        PIXCopyStringArgument(destination, limit, arg);
+        PIXCopyEventArguments(destination, limit, args...);
+#endif
+    }
+
+    inline UINT8 PIXGetEventSize(const UINT64* end, const UINT64* start)
+    {
+        const UINT64 actualEventSize = end - start;
+
+        return static_cast<UINT8>(actualEventSize > PIXEventsSizeMax ? PIXEventsSizeMax : actualEventSize);
+    }
+
+    template<typename STR>
+    inline UINT8 PIXEncodeStringIsAnsi()
+    {
+        return PIX_EVENT_METADATA_NONE;
+    }
+
+    template<>
+    inline UINT8 PIXEncodeStringIsAnsi<char*>()
+    {
+        return PIX_EVENT_METADATA_STRING_IS_ANSI;
+    }
+
+    template<>
+    inline UINT8 PIXEncodeStringIsAnsi<const char*>()
+    {
+        return PIX_EVENT_METADATA_STRING_IS_ANSI;
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXBeginEventAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+            return;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+        if (destination >= limit)
+            return;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        UINT64* eventDestination = destination++;
+        *destination++ = color;
+
+        PIXCopyStringArguments(destination, limit, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIX_EVENT_METADATA_HAS_COLOR |
+            PIXEncodeStringIsAnsi<STR>();
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    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();
+                UINT64* eventDestination = destination++;
+                *destination++ = color;
+
+                PIXCopyStringArguments(destination, limit, formatString, args...);
+                *destination = PIXEventsBlockEndMarker;
+
+                const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+                const UINT8 eventMetadata =
+                    PIX_EVENT_METADATA_HAS_COLOR |
+                    PIXEncodeStringIsAnsi<STR>();
+                *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+                threadInfo->destination = destination;
+            }
+            else
+            {
+                PIXBeginEventAllocate(threadInfo, color, formatString, args...);
+            }
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXBeginEventAllocate(PIXEventsThreadInfo* threadInfo, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+            return;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+        if (destination >= limit)
+            return;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        UINT64* eventDestination = destination++;
+
+        PIXCopyStringArguments(destination, limit, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIXEncodeStringIsAnsi<STR>() |
+            PIXEncodeIndexColor(color);
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXBeginEvent(UINT8 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();
+                UINT64* eventDestination = destination++;
+
+                PIXCopyStringArguments(destination, limit, formatString, args...);
+                *destination = PIXEventsBlockEndMarker;
+
+                const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+                const UINT8 eventMetadata =
+                    PIXEncodeStringIsAnsi<STR>() |
+                    PIXEncodeIndexColor(color);
+                *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+                threadInfo->destination = destination;
+            }
+            else
+            {
+                PIXBeginEventAllocate(threadInfo, color, formatString, args...);
+            }
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXSetMarkerAllocate(PIXEventsThreadInfo* threadInfo, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+            return;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+            return;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        UINT64* eventDestination = destination++;
+        *destination++ = color;
+
+        PIXCopyStringArguments(destination, limit, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIXEncodeStringIsAnsi<STR>() |
+            PIX_EVENT_METADATA_HAS_COLOR;
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    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();
+                UINT64* eventDestination = destination++;
+                *destination++ = color;
+
+                PIXCopyStringArguments(destination, limit, formatString, args...);
+                *destination = PIXEventsBlockEndMarker;
+
+                const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+                const UINT8 eventMetadata =
+                    PIXEncodeStringIsAnsi<STR>() |
+                    PIX_EVENT_METADATA_HAS_COLOR;
+                *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+                threadInfo->destination = destination;
+            }
+            else
+            {
+                PIXSetMarkerAllocate(threadInfo, color, formatString, args...);
+            }
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXSetMarkerAllocate(PIXEventsThreadInfo* threadInfo, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+            return;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+            return;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        UINT64* eventDestination = destination++;
+
+        PIXCopyStringArguments(destination, limit, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIXEncodeStringIsAnsi<STR>() |
+            PIXEncodeIndexColor(color);
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXSetMarker(UINT8 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();
+                UINT64* eventDestination = destination++;
+
+                PIXCopyStringArguments(destination, limit, formatString, args...);
+                *destination = PIXEventsBlockEndMarker;
+
+                const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+                const UINT8 eventMetadata =
+                    PIXEncodeStringIsAnsi<STR>() |
+                    PIXEncodeIndexColor(color);
+                *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+                threadInfo->destination = destination;
+            }
+            else
+            {
+                PIXSetMarkerAllocate(threadInfo, color, formatString, args...);
+            }
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXBeginEventOnContextCpuAllocate(UINT64*& eventDestination, UINT8& eventSize, PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        eventDestination = destination++;
+        *destination++ = color;
+
+        PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIX_EVENT_METADATA_ON_CONTEXT |
+            PIXEncodeStringIsAnsi<STR>() |
+            PIX_EVENT_METADATA_HAS_COLOR;
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXBeginEventOnContextCpu(UINT64*& eventDestination, UINT8& eventSize, void* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+        UINT64* limit = threadInfo->biasedLimit;
+        if (limit == nullptr)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        if (destination < limit)
+        {
+            limit += PIXEventsSafeFastCopySpaceQwords;
+            UINT64 time = PIXGetTimestampCounter();
+            eventDestination = destination++;
+            *destination++ = color;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = PIXEventsBlockEndMarker;
+
+            eventSize = PIXGetEventSize(destination, threadInfo->destination);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIX_EVENT_METADATA_HAS_COLOR;
+            *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+            threadInfo->destination = destination;
+        }
+        else
+        {
+            PIXBeginEventOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...);
+        }
+    }
+
+    template<typename CONTEXT, typename STR, typename... ARGS>
+    void PIXBeginEvent(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = nullptr;
+        UINT8 eventSize = 0u;
+
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+        PIXBeginEventOnContextCpu(destination, eventSize, context, color, formatString, args...);
+#endif
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+        if (destination != nullptr)
+        {
+            PIXInsertTimingMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast<void*>(destination), eventSize * sizeof(UINT64));
+        }
+        else
+#endif
+        {
+            UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+            destination = buffer;
+            UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+            UINT64* eventDestination = destination++;
+            *destination++ = color;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = 0ull;
+
+            eventSize = static_cast<const UINT8>(destination - buffer);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIX_EVENT_METADATA_HAS_COLOR;
+            *eventDestination = PIXEncodeEventInfo(0, PIXEvent_BeginEvent, eventSize, eventMetadata);
+            PIXInsertGPUMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#else
+            destination = PixEventsLegacy::EncodeBeginEventForContext(buffer, color, formatString, args...);
+            PIXBeginGPUEventOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#endif
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXBeginEventOnContextCpuAllocate(UINT64*& eventDestination, UINT8& eventSize, PIXEventsThreadInfo* threadInfo, void* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        eventDestination = destination++;
+
+        PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIX_EVENT_METADATA_ON_CONTEXT |
+            PIXEncodeStringIsAnsi<STR>() |
+            PIXEncodeIndexColor(color);
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXBeginEventOnContextCpu(UINT64*& eventDestination, UINT8& eventSize, void* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+        UINT64* limit = threadInfo->biasedLimit;
+        if (limit == nullptr)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        if (destination < limit)
+        {
+            limit += PIXEventsSafeFastCopySpaceQwords;
+            UINT64 time = PIXGetTimestampCounter();
+            eventDestination = destination++;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = PIXEventsBlockEndMarker;
+
+            eventSize = PIXGetEventSize(destination, threadInfo->destination);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIXEncodeIndexColor(color);
+            *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+            threadInfo->destination = destination;
+        }
+        else
+        {
+            PIXBeginEventOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...);
+        }
+    }
+
+    template<typename CONTEXT, typename STR, typename... ARGS>
+    void PIXBeginEvent(CONTEXT* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = nullptr;
+        UINT8 eventSize = 0u;
+
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+        PIXBeginEventOnContextCpu(destination, eventSize, context, color, formatString, args...);
+#endif
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+        if (destination != nullptr)
+        {
+            PIXInsertTimingMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast<void*>(destination), eventSize * sizeof(UINT64));
+        }
+        else
+#endif
+        {
+            UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+            destination = buffer;
+            UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+            UINT64* eventDestination = destination++;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = 0ull;
+
+            eventSize = static_cast<const UINT8>(destination - buffer);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIXEncodeIndexColor(color);
+            *eventDestination = PIXEncodeEventInfo(0, PIXEvent_BeginEvent, eventSize, eventMetadata);
+
+            PIXInsertGPUMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#else
+            destination = PixEventsLegacy::EncodeBeginEventForContext(buffer, color, formatString, args...);
+            PIXBeginGPUEventOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#endif
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXSetMarkerOnContextCpuAllocate(UINT64*& eventDestination, UINT8& eventSize, PIXEventsThreadInfo* threadInfo, void* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        eventDestination = destination++;
+        *destination++ = color;
+
+        PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIX_EVENT_METADATA_ON_CONTEXT |
+            PIXEncodeStringIsAnsi<STR>() |
+            PIX_EVENT_METADATA_HAS_COLOR;
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXSetMarkerOnContextCpu(UINT64*& eventDestination, UINT8& eventSize, void* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+        UINT64* limit = threadInfo->biasedLimit;
+        if (limit == nullptr)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        if (destination < limit)
+        {
+            limit += PIXEventsSafeFastCopySpaceQwords;
+            UINT64 time = PIXGetTimestampCounter();
+            eventDestination = destination++;
+            *destination++ = color;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = PIXEventsBlockEndMarker;
+
+            eventSize = PIXGetEventSize(destination, threadInfo->destination);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIX_EVENT_METADATA_HAS_COLOR;
+            *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+            threadInfo->destination = destination;
+        }
+        else
+        {
+            PIXSetMarkerOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...);
+        }
+    }
+
+    template<typename CONTEXT, typename STR, typename... ARGS>
+    void PIXSetMarker(CONTEXT* context, UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = nullptr;
+        UINT8 eventSize = 0u;
+
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+        PIXSetMarkerOnContextCpu(destination, eventSize, context, color, formatString, args...);
+#endif
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+        if (destination != nullptr)
+        {
+            PIXInsertTimingMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast<void*>(destination), eventSize * sizeof(UINT64));
+        }
+        else
+#endif
+        {
+            UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+            destination = buffer;
+            UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+            UINT64* eventDestination = destination++;
+            *destination++ = color;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = 0ull;
+
+            eventSize = static_cast<const UINT8>(destination - buffer);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIX_EVENT_METADATA_HAS_COLOR;
+            *eventDestination = PIXEncodeEventInfo(0, PIXEvent_SetMarker, eventSize, eventMetadata);
+            PIXInsertGPUMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#else
+            destination = PixEventsLegacy::EncodeSetMarkerForContext(buffer, color, formatString, args...);
+            PIXSetGPUMarkerOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#endif
+        }
+    }
+
+    template<typename STR, typename... ARGS>
+    __declspec(noinline) void PIXSetMarkerOnContextCpuAllocate(UINT64*& eventDestination, UINT8& eventSize, PIXEventsThreadInfo* threadInfo, void* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, false);
+        if (!time)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        eventDestination = destination++;
+
+        PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+        *destination = PIXEventsBlockEndMarker;
+
+        eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata =
+            PIX_EVENT_METADATA_ON_CONTEXT |
+            PIXEncodeStringIsAnsi<STR>() |
+            PIXEncodeIndexColor(color);
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+    }
+
+    template<typename STR, typename... ARGS>
+    void PIXSetMarkerOnContextCpu(UINT64*& eventDestination, UINT8& eventSize, void* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo();
+        UINT64* limit = threadInfo->biasedLimit;
+        if (limit == nullptr)
+        {
+            eventDestination = nullptr;
+            return;
+        }
+
+        UINT64* destination = threadInfo->destination;
+        if (destination < limit)
+        {
+            limit += PIXEventsSafeFastCopySpaceQwords;
+            UINT64 time = PIXGetTimestampCounter();
+            eventDestination = destination++;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = PIXEventsBlockEndMarker;
+
+            eventSize = PIXGetEventSize(destination, threadInfo->destination);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIXEncodeIndexColor(color);
+            *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata);
+
+            threadInfo->destination = destination;
+        }
+        else
+        {
+            PIXSetMarkerOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...);
+        }
+    }
+
+    template<typename CONTEXT, typename STR, typename... ARGS>
+    void PIXSetMarker(CONTEXT* context, UINT8 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = nullptr;
+        UINT8 eventSize = 0u;
+
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+        PIXSetMarkerOnContextCpu(destination, eventSize, context, color, formatString, args...);
+#endif
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+        if (destination != nullptr)
+        {
+            PIXInsertTimingMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast<void*>(destination), eventSize * sizeof(UINT64));
+        }
+        else
+#endif
+        {
+            UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+            destination = buffer;
+            UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+            UINT64* eventDestination = destination++;
+
+            PIXCopyStringArgumentsWithContext(destination, limit, context, formatString, args...);
+            *destination = 0ull;
+
+            eventSize = static_cast<const UINT8>(destination - buffer);
+            const UINT8 eventMetadata =
+                PIX_EVENT_METADATA_ON_CONTEXT |
+                PIXEncodeStringIsAnsi<STR>() |
+                PIXEncodeIndexColor(color);
+            *eventDestination = PIXEncodeEventInfo(0, PIXEvent_SetMarker, eventSize, eventMetadata);
+            PIXInsertGPUMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#else
+            destination = PixEventsLegacy::EncodeSetMarkerForContext(buffer, color, formatString, args...);
+            PIXSetGPUMarkerOnContext(context, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#endif
+        }
+    }
+
+    __declspec(noinline) inline void PIXEndEventAllocate(PIXEventsThreadInfo* threadInfo)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
+        if (!time)
+            return;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+            return;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        const UINT8 eventSize = 1;
+        const UINT8 eventMetadata = PIX_EVENT_METADATA_NONE;
+        *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent, eventSize, eventMetadata);
+        *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();
+                const UINT8 eventSize = 1;
+                const UINT8 eventMetadata = PIX_EVENT_METADATA_NONE;
+                *destination++ = PIXEncodeEventInfo(time, PIXEvent_EndEvent, eventSize, eventMetadata);
+                *destination = PIXEventsBlockEndMarker;
+
+                threadInfo->destination = destination;
+            }
+            else
+            {
+                PIXEndEventAllocate(threadInfo);
+            }
+        }
+    }
+
+    __declspec(noinline) inline UINT64* PIXEndEventOnContextCpuAllocate(PIXEventsThreadInfo* threadInfo, void* context)
+    {
+        UINT64 time = PIXEventsReplaceBlock(threadInfo, true);
+        if (!time)
+            return nullptr;
+
+        UINT64* destination = threadInfo->destination;
+        UINT64* limit = threadInfo->biasedLimit;
+
+        if (destination >= limit)
+            return nullptr;
+
+        limit += PIXEventsSafeFastCopySpaceQwords;
+        UINT64* eventDestination = destination++;
+#ifdef PIX_XBOX
+        UNREFERENCED_PARAMETER(context);
+#else
+        PIXCopyEventArgument(destination, limit, context);
+#endif
+        * destination = PIXEventsBlockEndMarker;
+
+        const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+        const UINT8 eventMetadata = PIX_EVENT_METADATA_ON_CONTEXT;
+        *eventDestination = PIXEncodeEventInfo(time, PIXEvent_EndEvent, eventSize, eventMetadata);
+
+        threadInfo->destination = destination;
+
+        return eventDestination;
+    }
+
+    inline UINT64* 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();
+                UINT64* eventDestination = destination++;
+#ifndef PIX_XBOX
+                PIXCopyEventArgument(destination, limit, context);
+#endif
+                * destination = PIXEventsBlockEndMarker;
+
+                const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination);
+                const UINT8 eventMetadata = PIX_EVENT_METADATA_ON_CONTEXT;
+                *eventDestination = PIXEncodeEventInfo(time, PIXEvent_EndEvent, eventSize, eventMetadata);
+
+                threadInfo->destination = destination;
+
+                return eventDestination;
+            }
+            else
+            {
+                return PIXEndEventOnContextCpuAllocate(threadInfo, context);
+            }
+        }
+
+        return nullptr;
+    }
+
+    template<typename CONTEXT>
+    void PIXEndEvent(CONTEXT* context)
+    {
+        UINT64* destination = nullptr;
+#ifdef PIX_CONTEXT_EMIT_CPU_EVENTS
+        destination = PIXEndEventOnContextCpu(context);
+#endif
+
+#ifdef PIX_USE_GPU_MARKERS_V2
+        if (destination != nullptr)
+        {
+            PIXInsertTimingMarkerOnContextForEndEvent(context, PIXEvent_EndEvent);
+        }
+        else
+#endif
+        {
+#ifdef PIX_USE_GPU_MARKERS_V2
+            UINT64 buffer[PIXEventsGraphicsRecordSpaceQwords];
+            destination = buffer;
+
+            UINT64* eventDestination = destination++;
+
+            const UINT8 eventSize = static_cast<const UINT8>(destination - buffer);
+            const UINT8 eventMetadata = PIX_EVENT_METADATA_NONE;
+            *eventDestination = PIXEncodeEventInfo(0, PIXEvent_EndEvent, eventSize, eventMetadata);
+            PIXInsertGPUMarkerOnContextForEndEvent(context, PIXEvent_EndEvent, static_cast<void*>(buffer), static_cast<UINT>(reinterpret_cast<BYTE*>(destination) - reinterpret_cast<BYTE*>(buffer)));
+#else
+            PIXEndGPUEventOnContext(context);
+#endif
+        }
+    }
+}
+
+#if defined(USE_PIX)
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXBeginEvent(UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template<typename... ARGS>
+void PIXSetMarker(UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginEvent(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetMarker(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+inline void PIXEndEvent()
+{
+    PIXEventsDetail::PIXEndEvent();
+}
+
+template<typename CONTEXT>
+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<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXBeginRetailEvent(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, static_cast<UINT64>(color), formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT, typename... ARGS>
+void PIXSetRetailMarker(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+{
+    PIXEventsDetail::PIXSetMarker(context, color, formatString, args...);
+}
+
+template<typename CONTEXT>
+void PIXEndRetailEvent(CONTEXT* context)
+{
+    PIXEventsDetail::PIXEndEvent(context);
+}
+
+template<typename CONTEXT>
+class PIXScopedEventObject
+{
+    CONTEXT* m_context;
+
+public:
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginEvent(m_context, color, formatString, args...);
+    }
+
+    ~PIXScopedEventObject()
+    {
+        PIXEndEvent(m_context);
+    }
+};
+
+template<typename CONTEXT>
+class PIXScopedRetailEventObject
+{
+    CONTEXT* m_context;
+
+public:
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedRetailEventObject(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args)
+        : m_context(context)
+    {
+        PIXBeginRetailEvent(m_context, color, formatString, args...);
+    }
+
+    ~PIXScopedRetailEventObject()
+    {
+        PIXEndRetailEvent(m_context);
+    }
+};
+
+template<>
+class PIXScopedEventObject<void>
+{
+public:
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT64 color, PCWSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT64 color, PCSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT32 color, PCWSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT32 color, PCSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(INT32 color, PCWSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(INT32 color, PCSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(DWORD color, PCWSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(DWORD color, PCSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT8 color, PCWSTR formatString, ARGS... args)
+    {
+        PIXBeginEvent(color, formatString, args...);
+    }
+
+    template<typename... ARGS>
+    PIXScopedEventObject(UINT8 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<PIXInferScopedEventType<decltype(context)>::Type> PIXGetScopedEventVariableName(pixEvent, __LINE__)(context, __VA_ARGS__)
+
+#ifdef PIX3__DEFINED_CONSTEXPR
+#undef constexpr
+#undef PIX3__DEFINED_CONSTEXPR
+#endif
+
+#endif // _PIXEvents_H__
+

+ 610 - 0
ThirdParty/Pix/Include/WinPixEventRuntime/PIXEventsCommon.h

@@ -0,0 +1,610 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// Don't include this file directly - use pix3.h
+
+#pragma once
+
+#ifndef _PIXEventsCommon_H_
+#define _PIXEventsCommon_H_
+
+//
+// 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;
+};
+
+extern "C" UINT64 WINAPI PIXEventsReplaceBlock(PIXEventsThreadInfo * threadInfo, bool getEarliestTime) noexcept;
+
+#define PIX_EVENT_METADATA_NONE                     0x0
+#define PIX_EVENT_METADATA_ON_CONTEXT               0x1
+#define PIX_EVENT_METADATA_STRING_IS_ANSI           0x2
+#define PIX_EVENT_METADATA_HAS_COLOR                0xF0
+
+#ifndef PIX_GAMING_XBOX
+#include "PIXEventsLegacy.h"
+#endif
+
+enum PIXEventType : UINT8
+{
+    PIXEvent_EndEvent       = 0x00,
+    PIXEvent_BeginEvent     = 0x01,
+    PIXEvent_SetMarker      = 0x02,
+};
+
+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-15 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;
+
+
+// V2 events
+
+// Bits 00..06 (7 bits) - Size in QWORDS
+static const UINT64 PIXEventsSizeWriteMask      = 0x000000000000007F;
+static const UINT64 PIXEventsSizeBitShift       = 0;
+static const UINT64 PIXEventsSizeReadMask       = PIXEventsSizeWriteMask << PIXEventsSizeBitShift;
+static const UINT64 PIXEventsSizeMax            = (1ull << 7) - 1ull;
+
+// Bits 07..11 (5 bits) - Event Type
+static const UINT64 PIXEventsTypeWriteMask      = 0x000000000000001F;
+static const UINT64 PIXEventsTypeBitShift       = 7;
+static const UINT64 PIXEventsTypeReadMask       = PIXEventsTypeWriteMask << PIXEventsTypeBitShift;
+
+// Bits 12..19 (8 bits) - Event Specific Metadata
+static const UINT64 PIXEventsMetadataWriteMask  = 0x00000000000000FF;
+static const UINT64 PIXEventsMetadataBitShift   = 12;
+static const UINT64 PIXEventsMetadataReadMask   = PIXEventsMetadataWriteMask << PIXEventsMetadataBitShift;
+
+// Buts 20..63 (44 bits) - Timestamp
+static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
+static const UINT64 PIXEventsTimestampBitShift  = 20;
+static const UINT64 PIXEventsTimestampReadMask  = PIXEventsTimestampWriteMask << PIXEventsTimestampBitShift;
+
+inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType, UINT8 eventSize, UINT8 eventMetadata)
+{
+    return
+        ((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) |
+        (((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift) |
+        (((UINT64)eventMetadata & PIXEventsMetadataWriteMask) << PIXEventsMetadataBitShift) |
+        (((UINT64)eventSize & PIXEventsSizeWriteMask) << PIXEventsSizeBitShift);
+}
+
+inline UINT8 PIXEncodeIndexColor(UINT8 color)
+{
+    // There are 8 index colors, indexed 0 (default) to 7
+    return (color & 0x7) << 4;
+}
+
+//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 void PIXEncodeStringInfo(UINT64*& destination, BOOL isANSI)
+{
+    const UINT64 encodedStringInfo = 
+        ((sizeof(UINT64) & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) |
+        (((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift);
+
+    *destination++ = encodedStringInfo;
+}
+
+template<UINT alignment, class T>
+inline bool PIXIsPointerAligned(T* pointer)
+{
+    return !(((UINT64)pointer) & (alignment - 1));
+}
+
+// Generic template version slower because of the additional clear write
+template<class T>
+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<INT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
+{
+    if (destination < limit)
+    {
+        *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
+        ++destination;
+    }
+}
+
+// unsigned int32 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument<UINT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
+{
+    if (destination < limit)
+    {
+        *destination = static_cast<UINT64>(argument);
+        ++destination;
+    }
+}
+
+// int64 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument<INT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
+{
+    if (destination < limit)
+    {
+        *reinterpret_cast<INT64*>(destination) = argument;
+        ++destination;
+    }
+}
+
+// unsigned int64 specialization to avoid slower double memory writes
+template<>
+inline void PIXCopyEventArgument<UINT64>(_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<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
+{
+    if (destination < limit)
+    {
+        *reinterpret_cast<double*>(destination) = static_cast<double>(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<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
+{
+    if (destination < limit)
+    {
+        *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
+        ++destination;
+    }
+}
+
+//UINT8 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<UINT8>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT8 argument)
+{
+    if (destination < limit)
+    {
+        *destination = static_cast<UINT64>(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<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
+{
+    if (destination < limit)
+    {
+        *destination = static_cast<UINT64>(argument);
+        ++destination;
+    }
+}
+
+inline void PIXCopyEventStringArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+    while (destination < limit)
+    {
+        UINT64 c = static_cast<UINT8>(argument[0]);
+        if (!c)
+        {
+            *destination++ = 0;
+            return;
+        }
+        UINT64 x = c;
+        c = static_cast<UINT8>(argument[1]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 8;
+        c = static_cast<UINT8>(argument[2]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 16;
+        c = static_cast<UINT8>(argument[3]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 24;
+        c = static_cast<UINT8>(argument[4]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 32;
+        c = static_cast<UINT8>(argument[5]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 40;
+        c = static_cast<UINT8>(argument[6]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 48;
+        c = static_cast<UINT8>(argument[7]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 56;
+        *destination++ = x;
+        argument += 8;
+    }
+}
+
+template<bool>
+inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+    PIXEncodeStringInfo(destination, TRUE);
+    PIXCopyEventStringArgumentSlow(destination, limit, argument);
+}
+
+template<>
+inline void PIXCopyEventArgumentSlow<false>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+    PIXCopyEventStringArgumentSlow(destination, limit, argument);
+}
+
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+
+inline void PIXCopyEventStringArgumentFast(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+    constexpr UINT64 mask1 = 0x0101010101010101ULL;
+    constexpr UINT64 mask2 = 0x8080808080808080ULL;
+    UINT64* source = (UINT64*)argument;
+
+    while (destination < limit)
+    {
+        UINT64 qword = *source++;
+        *destination++ = qword;
+
+        //check if any of the characters is a terminating zero
+        UINT64 isTerminated = (qword - mask1) & (~qword & mask2);
+
+        if (isTerminated)
+        {
+            break;
+        }
+    }
+}
+#endif
+
+template<>
+inline void PIXCopyEventArgument<PCSTR>(_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<8>(argument))
+            {
+                PIXEncodeStringInfo(destination, TRUE);
+                PIXCopyEventStringArgumentFast(destination, limit, argument);
+            }
+            else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+            {
+                PIXCopyEventArgumentSlow<true>(destination, limit, argument);
+            }
+        }
+        else
+        {
+            *destination++ = 0ull;
+        }
+    }
+}
+
+inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
+{
+    if (argument != nullptr)
+    {
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+        if (PIXIsPointerAligned<8>(argument))
+        {
+            PIXCopyEventStringArgumentFast(destination, limit, argument);
+        }
+        else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+        {
+            PIXCopyEventArgumentSlow<false>(destination, limit, argument);
+        }
+    }
+    else
+    {
+        *destination++ = 0ull;
+    }
+}
+
+template<>
+inline void PIXCopyEventArgument<PSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
+{
+    PIXCopyEventArgument(destination, limit, (PCSTR)argument);
+}
+
+inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
+{
+    PIXCopyStringArgument(destination, limit, (PCSTR)argument);
+}
+
+inline void PIXCopyEventStringArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+    while (destination < limit)
+    {
+        UINT64 c = static_cast<UINT16>(argument[0]);
+        if (!c)
+        {
+            *destination++ = 0;
+            return;
+        }
+        UINT64 x = c;
+        c = static_cast<UINT16>(argument[1]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 16;
+        c = static_cast<UINT16>(argument[2]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 32;
+        c = static_cast<UINT16>(argument[3]);
+        if (!c)
+        {
+            *destination++ = x;
+            return;
+        }
+        x |= c << 48;
+        *destination++ = x;
+        argument += 4;
+    }
+}
+
+template<bool>
+inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+    PIXEncodeStringInfo(destination, FALSE);
+    PIXCopyEventStringArgumentSlow(destination, limit, argument);
+}
+
+template<>
+inline void PIXCopyEventArgumentSlow<false>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+    PIXCopyEventStringArgumentSlow(destination, limit, argument);
+}
+
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+inline void PIXCopyEventStringArgumentFast(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+    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;
+        }
+    }
+}
+#endif
+
+template<>
+inline void PIXCopyEventArgument<PCWSTR>(_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<8>(argument))
+            {
+                PIXEncodeStringInfo(destination, FALSE);
+                PIXCopyEventStringArgumentFast(destination, limit, argument);
+            }
+            else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+            {
+                PIXCopyEventArgumentSlow<true>(destination, limit, argument);
+            }
+        }
+        else
+        {
+            *destination++ = 0ull;
+        }
+    }
+}
+
+inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
+{
+    if (argument != nullptr)
+    {
+#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+        if (PIXIsPointerAligned<8>(argument))
+        {
+            PIXCopyEventStringArgumentFast(destination, limit, argument);
+        }
+        else
+#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
+        {
+            PIXCopyEventArgumentSlow<false>(destination, limit, argument);
+        }
+    }
+    else
+    {
+        *destination++ = 0ull;
+    }
+}
+
+template<>
+inline void PIXCopyEventArgument<PWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument)
+{
+    PIXCopyEventArgument(destination, limit, (PCWSTR)argument);
+};
+
+inline void PIXCopyStringArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument)
+{
+    PIXCopyStringArgument(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<class T> struct PIXInferScopedEventType { typedef T Type; };
+template<class T> struct PIXInferScopedEventType<const T> { typedef T Type; };
+template<class T> struct PIXInferScopedEventType<T*> { typedef T Type; };
+template<class T> struct PIXInferScopedEventType<T* const> { typedef T Type; };
+template<> struct PIXInferScopedEventType<UINT64> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const UINT64> { typedef void Type; };
+template<> struct PIXInferScopedEventType<INT64> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const INT64> { typedef void Type; };
+template<> struct PIXInferScopedEventType<UINT> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const UINT> { typedef void Type; };
+template<> struct PIXInferScopedEventType<INT> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const INT> { typedef void Type; };
+template<> struct PIXInferScopedEventType<UINT8> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const UINT8> { typedef void Type; };
+template<> struct PIXInferScopedEventType<INT8> { typedef void Type; };
+template<> struct PIXInferScopedEventType<const INT8> { typedef void Type; };
+
+#endif //_PIXEventsCommon_H_

+ 565 - 0
ThirdParty/Pix/Include/WinPixEventRuntime/PIXEventsLegacy.h

@@ -0,0 +1,565 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+// Don't include this file directly - use pix3.h
+// This file encodes PIX events in the legacy PIX event format.
+
+#ifndef _PIXEventsLegacy_H_
+#define _PIXEventsLegacy_H_
+
+#include <cstdint>
+
+#if defined(_M_X64) || defined(_M_IX86)
+#include <emmintrin.h>
+#endif
+
+namespace PixEventsLegacy
+{
+    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;
+    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<UINT alignment, class T>
+    inline bool PIXIsPointerAligned(T* pointer)
+    {
+        return !(((UINT64)pointer) & (alignment - 1));
+    }
+
+    // Generic template version slower because of the additional clear write
+    template<class T>
+    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<INT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
+    {
+        if (destination < limit)
+        {
+            *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
+            ++destination;
+        }
+    }
+
+    // unsigned int32 specialization to avoid slower double memory writes
+    template<>
+    inline void PIXCopyEventArgument<UINT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
+    {
+        if (destination < limit)
+        {
+            *destination = static_cast<UINT64>(argument);
+            ++destination;
+        }
+    }
+
+    // int64 specialization to avoid slower double memory writes
+    template<>
+    inline void PIXCopyEventArgument<INT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
+    {
+        if (destination < limit)
+        {
+            *reinterpret_cast<INT64*>(destination) = argument;
+            ++destination;
+        }
+    }
+
+    // unsigned int64 specialization to avoid slower double memory writes
+    template<>
+    inline void PIXCopyEventArgument<UINT64>(_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<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
+    {
+        if (destination < limit)
+        {
+            *reinterpret_cast<double*>(destination) = static_cast<double>(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<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
+    {
+        if (destination < limit)
+        {
+            *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(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<unsigned char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument)
+    {
+        if (destination < limit)
+        {
+            *destination = static_cast<UINT64>(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<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
+    {
+        if (destination < limit)
+        {
+            *destination = static_cast<UINT64>(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<uint8_t>(argument[0]);
+            if (!c)
+            {
+                *destination++ = 0;
+                return;
+            }
+            UINT64 x = c;
+            c = static_cast<uint8_t>(argument[1]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 8;
+            c = static_cast<uint8_t>(argument[2]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 16;
+            c = static_cast<uint8_t>(argument[3]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 24;
+            c = static_cast<uint8_t>(argument[4]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 32;
+            c = static_cast<uint8_t>(argument[5]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 40;
+            c = static_cast<uint8_t>(argument[6]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 48;
+            c = static_cast<uint8_t>(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<PCSTR>(_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<PSTR>(_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<uint16_t>(argument[0]);
+            if (!c)
+            {
+                *destination++ = 0;
+                return;
+            }
+            UINT64 x = c;
+            c = static_cast<uint16_t>(argument[1]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 16;
+            c = static_cast<uint16_t>(argument[2]);
+            if (!c)
+            {
+                *destination++ = x;
+                return;
+            }
+            x |= c << 32;
+            c = static_cast<uint16_t>(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<PCWSTR>(_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;
+            }
+        }
+    }
+
+    inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
+    {
+        // nothing
+        UNREFERENCED_PARAMETER(destination);
+        UNREFERENCED_PARAMETER(limit);
+    }
+
+    template<typename ARG, typename... ARGS>
+    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<typename... ARGS>
+    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; }
+        static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
+
+        // 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; }
+        static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
+#else
+        static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; }
+        static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; }
+        static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
+#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; }
+        static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
+
+#ifdef PIX_XBOX
+        static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
+        static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
+        static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
+#else
+        static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; }
+        static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; }
+        static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
+#endif
+    };
+
+
+    template<size_t size, typename STR, typename... ARGS>
+    UINT64* EncodeBeginEventForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = buffer;
+        UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+        *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuBeginOnContext());
+        *destination++ = color;
+
+        PIXCopyEventArguments(destination, limit, formatString, args...);
+        *destination = 0ull;
+
+        return destination;
+    }
+
+    template<size_t size, typename STR, typename... ARGS>
+    UINT64* EncodeSetMarkerForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
+    {
+        UINT64* destination = buffer;
+        UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
+
+        *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuSetMarkerOnContext());
+        *destination++ = color;
+
+        PIXCopyEventArguments(destination, limit, formatString, args...);
+        *destination = 0ull;
+
+        return destination;
+    }
+}
+
+#endif //_PIXEventsLegacy_H_

+ 195 - 0
ThirdParty/Pix/Include/WinPixEventRuntime/pix3.h

@@ -0,0 +1,195 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#ifndef _PIX3_H_
+#define _PIX3_H_
+
+#include <sal.h>
+
+#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_GPU_TRACE               (1 << 9)
+#define PIX_CAPTURE_RESERVED                (1 << 15)
+
+union PIXCaptureParameters
+{
+    enum PIXCaptureStorage
+    {
+        Memory = 0,
+        MemoryCircular = 1, // Xbox only
+        FileCircular = 2, // PC only
+    };
+
+    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;
+        BOOL CapturePageFaultEvents;
+        BOOL CaptureVideoFrames; // Xbox only
+    } TimingCaptureParameters;
+
+    struct GpuTraceParameters // Xbox Series and newer only
+    {
+        PWSTR FileName;
+        UINT32 MaximumToolingMemorySizeMb;
+
+        BOOL CaptureGpuOccupancy;
+
+    } GpuTraceParameters;
+};
+
+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(XBOX) || defined(_XBOX_ONE) || defined(_DURANGO) || defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
+#define PIX_XBOX
+#if defined(_GAMING_XBOX) || defined(_GAMING_XBOX_SCARLETT)
+#define PIX_GAMING_XBOX
+#endif
+#endif
+
+#if !defined(PIX_USE_GPU_MARKERS_V2)
+#ifdef PIX_GAMING_XBOX 
+#define PIX_USE_GPU_MARKERS_V2
+#endif
+#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 UINT32 PIX_COLOR(UINT8 r, UINT8 g, UINT8 b) { return 0xff000000u | ((UINT32)r << 16) | ((UINT32)g << 8) | (UINT32)b; }
+inline UINT8 PIX_COLOR_INDEX(UINT8 i) { return i; }
+const UINT8 PIX_COLOR_DEFAULT = PIX_COLOR_INDEX(0);
+
+#endif // _PIX3_H_

+ 509 - 0
ThirdParty/Pix/Include/WinPixEventRuntime/pix3_win.h

@@ -0,0 +1,509 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+// 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 WINPIX_EVENT_* 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 used by pix.h in the Windows SDK.
+#define WINPIX_EVENT_UNICODE_VERSION 0
+#define WINPIX_EVENT_ANSI_VERSION 1
+
+// These values denote PIX marker event data that was created by the WinPixEventRuntime.
+// In early 2023 we revised the PIX marker format and defined a new version number.
+#define WINPIX_EVENT_PIX3BLOB_VERSION 2
+#define WINPIX_EVENT_PIX3BLOB_V2 6345127 // A number that other applications are unlikely to have used before
+
+// For backcompat reasons, the WinPixEventRuntime uses the older PIX3BLOB format when it passes data
+// into the D3D12 runtime. It will be updated to use the V2 format in the future.
+#define D3D12_EVENT_METADATA WINPIX_EVENT_PIX3BLOB_VERSION
+
+__forceinline UINT64 PIXGetTimestampCounter()
+{
+    LARGE_INTEGER time = {};
+    QueryPerformanceCounter(&time);
+    return static_cast<UINT64>(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 <shlobj.h>
+#include <strsafe.h>
+#include <knownfolders.h>
+#include <shellapi.h>
+
+#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)
+{
+    // 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
+
+#if defined(__d3d12_h__)
+
+inline void PIXInsertTimingMarkerOnContextForBeginEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandList->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertTimingMarkerOnContextForBeginEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandQueue->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertTimingMarkerOnContextForSetMarker(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandList->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertTimingMarkerOnContextForSetMarker(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandQueue->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertTimingMarkerOnContextForEndEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandList->EndEvent();
+}
+
+inline void PIXInsertTimingMarkerOnContextForEndEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandQueue->EndEvent();
+}
+
+inline void PIXInsertGPUMarkerOnContextForBeginEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandList->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertGPUMarkerOnContextForBeginEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandQueue->BeginEvent(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertGPUMarkerOnContextForSetMarker(_In_ ID3D12GraphicsCommandList* commandList, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandList->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertGPUMarkerOnContextForSetMarker(_In_ ID3D12CommandQueue* commandQueue, UINT8 eventType, _In_reads_bytes_(size) void* data, UINT size)
+{
+    UNREFERENCED_PARAMETER(eventType);
+    commandQueue->SetMarker(WINPIX_EVENT_PIX3BLOB_V2, data, size);
+}
+
+inline void PIXInsertGPUMarkerOnContextForEndEvent(_In_ ID3D12GraphicsCommandList* commandList, UINT8, void*, UINT)
+{
+    commandList->EndEvent();
+}
+
+inline void PIXInsertGPUMarkerOnContextForEndEvent(_In_ ID3D12CommandQueue* commandQueue, UINT8, void*, UINT)
+{
+    commandQueue->EndEvent();
+}
+
+#endif
+
+#endif //_PIX3_WIN_H_

+ 579 - 0
ThirdParty/Pix/ThirdPartyNotices.txt

@@ -0,0 +1,579 @@
+THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
+
+Note: While Microsoft is not the author of the files below, Microsoft is
+offering you a license subject to the terms of the Microsoft Software License
+Terms for Microsoft PIX Developer Tool (the "Microsoft Program"). Microsoft
+reserves all other rights. The notices below are provided for informational
+purposes only and are not the license terms under which Microsoft distributes
+these files.
+
+The Microsoft Program includes the following third-party software:
+
+1. Boost v. 1.66.0 (https://sourceforge.net/projects/boost/files/boost/1.66.0)
+2. fmt v4.1.0 (https://github.com/fmtlib/fmt/releases/tag/4.1.0)
+3. SQLite 3 (http://www.sqlite.org/)
+4. AMD PIX Plugin
+5. nlohmann JSON (https://github.com/nlohmann/json)
+6. PresentMon (https://github.com/GameTechDev/PresentMon)
+7. DirectXTex (https://github.com/microsoft/directxtex)
+8. DirectXTK12 (https://github.com/microsoft/DirectXTK12)
+9. Guidelines Support Library (GSL) (https://github.com/microsoft/GSL)
+10. Windows Implementation Library (WIL) (https://github.com/microsoft/wil)
+11. GoogleTest (https://github.com/google/googletest/)
+12. Newtonsoft.Json (https://www.newtonsoft.com/json)
+13. WIX (https://wixtoolset.org/)
+14. Moq (https://github.com/moq/moq)
+15. FluentAssertions (https://github.com/fluentassertions/fluentassertions)
+16. .NET Community Toolkit (https://github.com/CommunityToolkit/dotnet)
+17. LiveCharts (https://lvcharts.com)
+18. NVIDIA PIX Plugin
+
+As the recipient of the above third-party software, Microsoft sets forth a copy
+of the notices and other information below.
+
+
+BOOST NOTICES AND INFORMATION BEGIN HERE
+========================================
+
+Boost v. 1.66.0
+Copyright Beman Dawes, David Abrahams, 1998-2005
+Copyright Rene Rivera 2006-2007
+Provided for Informational Purposes Only
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by this
+license (the "Software") to use, reproduce, display, distribute, execute, and
+transmit the Software, and to prepare derivative works of the Software, and to
+permit third-parties to whom the Software is furnished to do so, all subject to
+the following:
+
+The copyright notices in the Software and this entire statement, including the
+above license grant, this restriction and the following disclaimer, must be
+included in all copies of the Software, in whole or in part, and all derivative
+works of the Software, unless such copies or derivative works are solely in the
+form of machine-executable object code generated by a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY
+DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+
+END OF BOOST NOTICES AND INFORMATION
+====================================
+
+FMT NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+fmt v4.1.0
+Copyright (c) 2012 - 2016, Victor Zverovich
+Provided for Informational Purposes Only
+BSD 2-clause
+
+
+Copyright (c) 2012 - 2016, Victor Zverovich
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+END OF FMT NOTICES AND INFORMATION
+==================================
+
+SQLITE3 NOTICES AND INFORMATION BEGIN HERE
+==========================================
+
+https://www.sqlite.org/copyright.html
+SQLite Is Public Domain
+
+All of the code and documentation in SQLite has been dedicated to the public
+domain by the authors. All code authors, and representatives of the companies
+they work for, have signed affidavits dedicating their contributions to the
+public domain and originals of those signed affidavits are stored in a firesafe
+at the main offices of Hwaci. Anyone is free to copy, modify, publish, use,
+compile, sell, or distribute the original SQLite code, either in source code
+form or as a compiled binary, for any purpose, commercial or non-commercial, and
+by any means.
+
+The previous paragraph applies to the deliverable code and documentation in SQLite -
+those parts of the SQLite library that you actually bundle and ship with a larger
+application. Some scripts used as part of the build process (for example the "configure"
+scripts generated by autoconf) might fall under other open-source licenses. Nothing
+from these build scripts ever reaches the final deliverable SQLite library, however,
+and so the licenses associated with those scripts should not be a factor in assessing
+your rights to copy and use the SQLite library.
+
+All of the deliverable code in SQLite has been written from scratch. No code has been
+taken from other projects or from the open internet. Every line of code can be traced
+back to its original author, and all of those authors have public domain dedications
+on file. So the SQLite code base is clean and is uncontaminated with licensed code
+from other projects.
+
+END OF SQLITE3 NOTICES AND INFORMATION
+======================================
+
+AMD NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+AMD copyrighted code (MIT) 
+Copyright (c) 2017-2023 Advanced Micro Devices, Inc. All rights reserved. 
+ 
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal 
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions: 
+ 
+The above copyright notice and this permission notice shall be included in 
+all copies or substantial portions of the Software. 
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
+THE SOFTWARE.
+
+
+Microsoft copyrighted code (MIT)
+Copyright (c) Microsoft. All rights reserved. 
+
+This code is licensed under the MIT License (MIT). 
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+END OF AMD NOTICES AND INFORMATION
+==================================
+
+NLOHMANN JSON NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+MIT License 
+
+Copyright (c) 2013-2021 Niels Lohmann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+END OF NLOHMANN JSON NOTICES AND INFORMATION
+==================================
+
+PRESENTMON NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+Copyright (C) 2017-2021 Intel Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
+OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
+
+END OF PRESENTMON NOTICES AND INFORMATION
+==================================
+
+DIRECTXTEX NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+Copyright (c) 2011-2021 Microsoft Corp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all copies
+or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+END OF DIRECTXTEX NOTICES AND INFORMATION
+==================================
+
+DIRECTXTK12 NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+Copyright (c) 2016-2021 Microsoft Corp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all copies
+or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+END OF DIRECTXTK12 NOTICES AND INFORMATION
+==================================
+
+GSL NOTICES AND INFORMATION BEGIN HERE
+======================================
+
+Copyright (c) 2015 Microsoft Corporation. All rights reserved. 
+ 
+This code is licensed under the MIT License (MIT). 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the "Software"), to deal 
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do 
+so, subject to the following conditions: 
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software. 
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
+THE SOFTWARE. 
+
+END OF GSL NOTICES AND INFORMATION
+==================================
+
+WIL NOTICES AND INFORMATION BEGIN HERE
+======================================
+MIT License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
+END OF WIL NOTICES AND INFORMATION
+==================================
+
+GOOGLETEST NOTICES AND INFORMATION BEGIN HERE
+======================================
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+END OF GOOGLETEST NOTICES AND INFORMATION
+==================================
+
+NEWTONSOFT.JSON NOTICES AND INFORMATION BEGIN HERE
+======================================
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+END OF NEWTONSOFT.JSON NOTICES AND INFORMATION
+=================================
+
+WIX NOTICES AND INFORMATION BEGIN HERE
+======================================
+Copyright (c) .NET Foundation and contributors. This software is released under
+the Microsoft Reciprocal License (MS-RL) (the "License"); you may not use the
+software except in compliance with the License.
+
+The text of the Microsoft Reciprocal License (MS-RL) can be found online at:
+http://opensource.org/licenses/ms-rl
+
+
+Microsoft Reciprocal License (MS-RL)
+
+This license governs use of the accompanying software. If you use the software,
+you accept this license. If you do not accept the license, do not use the
+software.
+
+1. Definitions The terms "reproduce," "reproduction," "derivative works," and
+"distribution" have the same meaning here as under U.S. copyright law. A
+"contribution" is the original software, or any additions or changes to the
+software. A "contributor" is any person that distributes its contribution under
+this license. "Licensed patents" are a contributor's patent claims that read
+directly on its contribution.
+
+2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license,
+including the license conditions and limitations in section 3, each contributor
+grants you a non-exclusive, worldwide, royalty-free copyright license to
+reproduce its contribution, prepare derivative works of its contribution, and
+distribute its contribution or any derivative works that you create. (B) Patent
+Grant- Subject to the terms of this license, including the license conditions and
+limitations in section 3, each contributor grants you a non-exclusive, worldwide,
+royalty-free license under its licensed patents to make, have made, use, sell,
+offer for sale, import, and/or otherwise dispose of its contribution in the
+software or derivative works of the contribution in the software.
+
+3. Conditions and Limitations (A) Reciprocal Grants- For any file you distribute
+that contains code from the software (in source code or binary format), you must
+provide recipients the source code to that file along with a copy of this
+license, which license will govern that file. You may license other files that
+are entirely your own work and do not contain code from the software under any
+terms you choose. (B) No Trademark License- This license does not grant you
+rights to use any contributors' name, logo, or trademarks. (C) If you bring a
+patent claim against any contributor over patents that you claim are infringed by
+the software, your patent license from such contributor to the software ends
+automatically. (D) If you distribute any portion of the software, you must retain
+all copyright, patent, trademark, and attribution notices that are present in the
+software. (E) If you distribute any portion of the software in source code form,
+you may do so only under this license by including a complete copy of this
+license with your distribution. If you distribute any portion of the software in
+compiled or object code form, you may only do so under a license that complies
+with this license. (F) The software is licensed "as-is." You bear the risk of
+using it. The contributors give no express warranties, guarantees or conditions.
+You may have additional consumer rights under your local laws which this license
+cannot change. To the extent permitted under your local laws, the contributors
+exclude the implied warranties of merchantability, fitness for a particular
+purpose and non-infringement.
+
+END OF WIX NOTICES AND INFORMATION
+=================================
+
+
+MOQ NOTICES AND INFORMATION BEGIN HERE
+======================================
+MIT License
+
+Copyright (c) Daniel Cazzulino and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+END OF MOQ NOTICES AND INFORMATION
+==================================
+
+
+FLUENTASSERTIONS NOTICES AND INFORMATION BEGIN HERE
+===================================================
+Copyright [2010-2021] [Dennis Doomen]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+END OF FLUENTASSERTIONS NOTICES AND INFORMATION
+===============================================
+
+.NET COMMUNITY TOOLKIT NOTICES AND INFORMATION BEGIN HERE
+======================================
+MIT License
+
+Copyright © .NET Foundation and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+END OF .NET COMMUNITY TOOLKIT NOTICES AND INFORMATION
+==================================
+
+LIVE CHARTS NOTICES AND INFORMATION BEGIN HERE
+======================================
+MIT License
+
+Copyright (c) 2021 Alberto Rodriguez Orozco
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+END OF LIVE CHARTS NOTICES AND INFORMATION
+==================================
+
+NVIDIA PIX PLUGIN NOTICES AND INFORMATION BEGIN HERE
+======================================
+Copyright (c) Microsoft Corporation.
+Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+END OF NVIDIA PIX PLUGIN NOTICES AND INFORMATION
+==================================

BIN
ThirdParty/Pix/bin/x64/WinPixEventRuntime.dll


BIN
ThirdParty/Pix/bin/x64/WinPixEventRuntime.lib


+ 21 - 0
ThirdParty/Pix/license.txt

@@ -0,0 +1,21 @@
+Copyright (c) Microsoft Corporation.
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.