diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp index 234c347c5..b86cf0665 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/commandlist.cpp @@ -13,6 +13,10 @@ #include +#ifdef KOPE_PIX +#include +#endif + void kope_d3d12_command_list_begin_render_pass(kope_g5_command_list *list, const kope_g5_render_pass_parameters *parameters) { list->d3d12.compute_pipeline_set = false; @@ -641,10 +645,20 @@ void kope_d3d12_command_list_set_name(kope_g5_command_list *list, const char *na list->d3d12.list->SetName(wstr); } -void kope_d3d12_command_list_push_debug_group(kope_g5_command_list *list, const char *name) {} +void kope_d3d12_command_list_push_debug_group(kope_g5_command_list *list, const char *name) { +#ifdef KOPE_PIX + PIXBeginEvent(list->d3d12.list, 0, "%s", name); +#endif +} -void kope_d3d12_command_list_pop_debug_group(kope_g5_command_list *list) {} +void kope_d3d12_command_list_pop_debug_group(kope_g5_command_list *list) { +#ifdef KOPE_PIX + PIXEndEvent(list->d3d12.list); +#endif +} void kope_d3d12_command_list_insert_debug_marker(kope_g5_command_list *list, const char *name) { - // PIXSetMarker(); +#ifdef KOPE_PIX + PIXSetMarker(list->d3d12.list, 0, "%s", name); +#endif } diff --git a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/d3d12unit.h b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/d3d12unit.h index de13c8893..ed1c6af87 100644 --- a/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/d3d12unit.h +++ b/Backends/Graphics5/Direct3D12/Sources/kope/direct3d12/d3d12unit.h @@ -12,7 +12,9 @@ #define NOCLIPBOARD #define NOCOLOR #define NOCOMM +#ifndef KOPE_PIX #define NOCTLMGR +#endif #define NODEFERWINDOWPOS #define NODRAWTEXT #define NOGDI @@ -34,7 +36,9 @@ #define NORASTEROPS #define NOSCROLL #define NOSERVICE +#ifndef KOPE_PIX #define NOSHOWWINDOW +#endif #define NOSOUND #define NOSYSCOMMANDS #define NOSYSMETRICS @@ -42,7 +46,9 @@ // #define NOUSER #define NOVIRTUALKEYCODES #define NOWH +#ifndef KOPE_PIX #define NOWINMESSAGES +#endif #define NOWINOFFSETS #define NOWINSTYLES #define WIN32_LEAN_AND_MEAN diff --git a/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEvents.h b/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEvents.h new file mode 100644 index 000000000..52dd8bcbd --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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 + 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 + 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 + 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(actualEventSize > PIXEventsSizeMax ? PIXEventsSizeMax : actualEventSize); + } + + template + inline UINT8 PIXEncodeStringIsAnsi() + { + return PIX_EVENT_METADATA_NONE; + } + + template<> + inline UINT8 PIXEncodeStringIsAnsi() + { + return PIX_EVENT_METADATA_STRING_IS_ANSI; + } + + template<> + inline UINT8 PIXEncodeStringIsAnsi() + { + return PIX_EVENT_METADATA_STRING_IS_ANSI; + } + + template + __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(); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + void PIXBeginEvent(UINT64 color, STR formatString, ARGS... args) + { + PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); + UINT64* limit = threadInfo->biasedLimit; + if (limit != nullptr) + { + UINT64* destination = threadInfo->destination; + if (destination < limit) + { + limit += PIXEventsSafeFastCopySpaceQwords; + UINT64 time = PIXGetTimestampCounter(); + 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(); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXBeginEventAllocate(threadInfo, color, formatString, args...); + } + } + } + + template + __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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXBeginEventAllocate(threadInfo, color, formatString, args...); + } + } + } + + template + __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() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + void PIXSetMarker(UINT64 color, STR formatString, ARGS... args) + { + PIXEventsThreadInfo* threadInfo = PIXGetThreadInfo(); + UINT64* limit = threadInfo->biasedLimit; + if (limit != nullptr) + { + UINT64* destination = threadInfo->destination; + if (destination < limit) + { + limit += PIXEventsSafeFastCopySpaceQwords; + UINT64 time = PIXGetTimestampCounter(); + UINT64* eventDestination = destination++; + *destination++ = color; + + PIXCopyStringArguments(destination, limit, formatString, args...); + *destination = PIXEventsBlockEndMarker; + + const UINT8 eventSize = PIXGetEventSize(destination, threadInfo->destination); + const UINT8 eventMetadata = + PIXEncodeStringIsAnsi() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXSetMarkerAllocate(threadInfo, color, formatString, args...); + } + } + } + + template + __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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXSetMarkerAllocate(threadInfo, color, formatString, args...); + } + } + } + + template + __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() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + 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 + 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(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(destination - buffer); + const UINT8 eventMetadata = + PIX_EVENT_METADATA_ON_CONTEXT | + PIXEncodeStringIsAnsi() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(0, PIXEvent_BeginEvent, eventSize, eventMetadata); + PIXInsertGPUMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#else + destination = PixEventsLegacy::EncodeBeginEventForContext(buffer, color, formatString, args...); + PIXBeginGPUEventOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#endif + } + } + + template + __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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_BeginEvent, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXBeginEventOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...); + } + } + + template + 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(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(destination - buffer); + const UINT8 eventMetadata = + PIX_EVENT_METADATA_ON_CONTEXT | + PIXEncodeStringIsAnsi() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(0, PIXEvent_BeginEvent, eventSize, eventMetadata); + + PIXInsertGPUMarkerOnContextForBeginEvent(context, PIXEvent_BeginEvent, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#else + destination = PixEventsLegacy::EncodeBeginEventForContext(buffer, color, formatString, args...); + PIXBeginGPUEventOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#endif + } + } + + template + __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() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + 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 + 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(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(destination - buffer); + const UINT8 eventMetadata = + PIX_EVENT_METADATA_ON_CONTEXT | + PIXEncodeStringIsAnsi() | + PIX_EVENT_METADATA_HAS_COLOR; + *eventDestination = PIXEncodeEventInfo(0, PIXEvent_SetMarker, eventSize, eventMetadata); + PIXInsertGPUMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#else + destination = PixEventsLegacy::EncodeSetMarkerForContext(buffer, color, formatString, args...); + PIXSetGPUMarkerOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#endif + } + } + + template + __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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + + template + 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() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(time, PIXEvent_SetMarker, eventSize, eventMetadata); + + threadInfo->destination = destination; + } + else + { + PIXSetMarkerOnContextCpuAllocate(eventDestination, eventSize, threadInfo, context, color, formatString, args...); + } + } + + template + 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(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(destination - buffer); + const UINT8 eventMetadata = + PIX_EVENT_METADATA_ON_CONTEXT | + PIXEncodeStringIsAnsi() | + PIXEncodeIndexColor(color); + *eventDestination = PIXEncodeEventInfo(0, PIXEvent_SetMarker, eventSize, eventMetadata); + PIXInsertGPUMarkerOnContextForSetMarker(context, PIXEvent_SetMarker, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#else + destination = PixEventsLegacy::EncodeSetMarkerForContext(buffer, color, formatString, args...); + PIXSetGPUMarkerOnContext(context, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(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 + 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(destination - buffer); + const UINT8 eventMetadata = PIX_EVENT_METADATA_NONE; + *eventDestination = PIXEncodeEventInfo(0, PIXEvent_EndEvent, eventSize, eventMetadata); + PIXInsertGPUMarkerOnContextForEndEvent(context, PIXEvent_EndEvent, static_cast(buffer), static_cast(reinterpret_cast(destination) - reinterpret_cast(buffer))); +#else + PIXEndGPUEventOnContext(context); +#endif + } + } +} + +#if defined(USE_PIX) + +template +void PIXBeginEvent(UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(color, formatString, args...); +} + +template +void PIXBeginEvent(UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(color, formatString, args...); +} + +template +void PIXBeginEvent(UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(color, formatString, args...); +} + +template +void PIXBeginEvent(UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(color, formatString, args...); +} + +template +void PIXSetMarker(UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(color, formatString, args...); +} + +template +void PIXSetMarker(UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(color, formatString, args...); +} + +template +void PIXSetMarker(UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(color, formatString, args...); +} + +template +void PIXSetMarker(UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(color, formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginEvent(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetMarker(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +inline void PIXEndEvent() +{ + PIXEventsDetail::PIXEndEvent(); +} + +template +void PIXEndEvent(CONTEXT* context) +{ + PIXEventsDetail::PIXEndEvent(context); +} + +#else // USE_PIX_RETAIL + +inline void PIXBeginEvent(UINT64, _In_ PCSTR, ...) {} +inline void PIXBeginEvent(UINT64, _In_ PCWSTR, ...) {} +inline void PIXBeginEvent(void*, UINT64, _In_ PCSTR, ...) {} +inline void PIXBeginEvent(void*, UINT64, _In_ PCWSTR, ...) {} +inline void PIXEndEvent() {} +inline void PIXEndEvent(void*) {} +inline void PIXSetMarker(UINT64, _In_ PCSTR, ...) {} +inline void PIXSetMarker(UINT64, _In_ PCWSTR, ...) {} +inline void PIXSetMarker(void*, UINT64, _In_ PCSTR, ...) {} +inline void PIXSetMarker(void*, UINT64, _In_ PCWSTR, ...) {} + +#endif // USE_PIX + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, static_cast(color), formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXBeginRetailEvent(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXBeginEvent(context, color, formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, static_cast(color), formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXSetRetailMarker(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args) +{ + PIXEventsDetail::PIXSetMarker(context, color, formatString, args...); +} + +template +void PIXEndRetailEvent(CONTEXT* context) +{ + PIXEventsDetail::PIXEndEvent(context); +} + +template +class PIXScopedEventObject +{ + CONTEXT* m_context; + +public: + template + PIXScopedEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + template + PIXScopedEventObject(CONTEXT* context, UINT8 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginEvent(m_context, color, formatString, args...); + } + + ~PIXScopedEventObject() + { + PIXEndEvent(m_context); + } +}; + +template +class PIXScopedRetailEventObject +{ + CONTEXT* m_context; + +public: + template + PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, UINT64 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, UINT32 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, UINT32 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, INT32 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, INT32 color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, DWORD color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, DWORD color, PCSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + PIXScopedRetailEventObject(CONTEXT* context, UINT8 color, PCWSTR formatString, ARGS... args) + : m_context(context) + { + PIXBeginRetailEvent(m_context, color, formatString, args...); + } + + template + 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 +{ +public: + template + PIXScopedEventObject(UINT64 color, PCWSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(UINT64 color, PCSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(UINT32 color, PCWSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(UINT32 color, PCSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(INT32 color, PCWSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(INT32 color, PCSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(DWORD color, PCWSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(DWORD color, PCSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + PIXScopedEventObject(UINT8 color, PCWSTR formatString, ARGS... args) + { + PIXBeginEvent(color, formatString, args...); + } + + template + 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::Type> PIXGetScopedEventVariableName(pixEvent, __LINE__)(context, __VA_ARGS__) + +#ifdef PIX3__DEFINED_CONSTEXPR +#undef constexpr +#undef PIX3__DEFINED_CONSTEXPR +#endif + +#endif // _PIXEvents_H__ + diff --git a/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEventsCommon.h b/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEventsCommon.h new file mode 100644 index 000000000..69a9bb941 --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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 +inline bool PIXIsPointerAligned(T* pointer) +{ + return !(((UINT64)pointer) & (alignment - 1)); +} + +// Generic template version slower because of the additional clear write +template +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument) +{ + if (destination < limit) + { + *destination = 0ull; + *((T*)destination) = argument; + ++destination; + } +} + +// int32 specialization to avoid slower double memory writes +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument) +{ + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } +} + +// unsigned int32 specialization to avoid slower double memory writes +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument) +{ + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } +} + +// int64 specialization to avoid slower double memory writes +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument) +{ + if (destination < limit) + { + *reinterpret_cast(destination) = argument; + ++destination; + } +} + +// unsigned int64 specialization to avoid slower double memory writes +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument) +{ + if (destination < limit) + { + *destination = argument; + ++destination; + } +} + +//floats must be cast to double during writing the data to be properly printed later when reading the data +//this is needed because when float is passed to varargs function it's cast to double +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument) +{ + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } +} + +//char has to be cast to a longer signed integer type +//this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument) +{ + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } +} + +//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(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT8 argument) +{ + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } +} + +//bool has to be cast to an integer since it's not explicitly supported by string format routines +//there's no format specifier for bool type, but it should work with integer format specifiers +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument) +{ + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } +} + +inline void PIXCopyEventStringArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) +{ + while (destination < limit) + { + UINT64 c = static_cast(argument[0]); + if (!c) + { + *destination++ = 0; + return; + } + UINT64 x = c; + c = static_cast(argument[1]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 8; + c = static_cast(argument[2]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 16; + c = static_cast(argument[3]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 24; + c = static_cast(argument[4]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 32; + c = static_cast(argument[5]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 40; + c = static_cast(argument[6]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 48; + c = static_cast(argument[7]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 56; + *destination++ = x; + argument += 8; + } +} + +template +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(_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(_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(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(destination, limit, argument); + } + } + else + { + *destination++ = 0ull; + } +} + +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument) +{ + PIXCopyEventArgument(destination, limit, (PCSTR)argument); +} + +inline void 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(argument[0]); + if (!c) + { + *destination++ = 0; + return; + } + UINT64 x = c; + c = static_cast(argument[1]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 16; + c = static_cast(argument[2]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 32; + c = static_cast(argument[3]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 48; + *destination++ = x; + argument += 4; + } +} + +template +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(_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(_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(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(destination, limit, argument); + } + } + else + { + *destination++ = 0ull; + } +} + +template<> +inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument) +{ + PIXCopyEventArgument(destination, limit, (PCWSTR)argument); +}; + +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 struct PIXInferScopedEventType { typedef T Type; }; +template struct PIXInferScopedEventType { typedef T Type; }; +template struct PIXInferScopedEventType { typedef T Type; }; +template struct PIXInferScopedEventType { typedef T Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; +template<> struct PIXInferScopedEventType { typedef void Type; }; + +#endif //_PIXEventsCommon_H_ diff --git a/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEventsLegacy.h b/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/PIXEventsLegacy.h new file mode 100644 index 000000000..53230138b --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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 + +#if defined(_M_X64) || defined(_M_IX86) +#include +#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 + inline bool PIXIsPointerAligned(T* pointer) + { + return !(((UINT64)pointer) & (alignment - 1)); + } + + // Generic template version slower because of the additional clear write + template + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument) + { + if (destination < limit) + { + *destination = 0ull; + *((T*)destination) = argument; + ++destination; + } + } + + // int32 specialization to avoid slower double memory writes + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument) + { + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } + } + + // unsigned int32 specialization to avoid slower double memory writes + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument) + { + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } + } + + // int64 specialization to avoid slower double memory writes + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument) + { + if (destination < limit) + { + *reinterpret_cast(destination) = argument; + ++destination; + } + } + + // unsigned int64 specialization to avoid slower double memory writes + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument) + { + if (destination < limit) + { + *destination = argument; + ++destination; + } + } + + //floats must be cast to double during writing the data to be properly printed later when reading the data + //this is needed because when float is passed to varargs function it's cast to double + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument) + { + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } + } + + //char has to be cast to a longer signed integer type + //this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument) + { + if (destination < limit) + { + *reinterpret_cast(destination) = static_cast(argument); + ++destination; + } + } + + //unsigned char has to be cast to a longer unsigned integer type + //this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument) + { + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } + } + + //bool has to be cast to an integer since it's not explicitly supported by string format routines + //there's no format specifier for bool type, but it should work with integer format specifiers + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument) + { + if (destination < limit) + { + *destination = static_cast(argument); + ++destination; + } + } + + inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) + { + *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE); + while (destination < limit) + { + UINT64 c = static_cast(argument[0]); + if (!c) + { + *destination++ = 0; + return; + } + UINT64 x = c; + c = static_cast(argument[1]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 8; + c = static_cast(argument[2]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 16; + c = static_cast(argument[3]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 24; + c = static_cast(argument[4]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 32; + c = static_cast(argument[5]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 40; + c = static_cast(argument[6]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 48; + c = static_cast(argument[7]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 56; + *destination++ = x; + argument += 8; + } + } + + inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) + { +#if PIX_ENABLE_BLOCK_ARGUMENT_COPY + if (PIXIsPointerAligned<8>(argument)) + { + *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE); + UINT64* source = (UINT64*)argument; + while (destination < limit) + { + UINT64 qword = *source++; + *destination++ = qword; + //check if any of the characters is a terminating zero + if (!((qword & 0xFF00000000000000) && + (qword & 0xFF000000000000) && + (qword & 0xFF0000000000) && + (qword & 0xFF00000000) && + (qword & 0xFF000000) && + (qword & 0xFF0000) && + (qword & 0xFF00) && + (qword & 0xFF))) + { + break; + } + } + } + else +#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY + { + PIXCopyEventArgumentSlowest(destination, limit, argument); + } + } + + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument) + { + if (destination < limit) + { + if (argument != nullptr) + { +#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY + if (PIXIsPointerAligned<16>(argument)) + { + *destination++ = PIXEncodeStringInfo(0, 16, TRUE, FALSE); + __m128i zero = _mm_setzero_si128(); + if (PIXIsPointerAligned<16>(destination)) + { + while (destination < limit) + { + __m128i mem = _mm_load_si128((__m128i*)argument); + _mm_store_si128((__m128i*)destination, mem); + //check if any of the characters is a terminating zero + __m128i res = _mm_cmpeq_epi8(mem, zero); + destination += 2; + if (_mm_movemask_epi8(res)) + break; + argument += 16; + } + } + else + { + while (destination < limit) + { + __m128i mem = _mm_load_si128((__m128i*)argument); + _mm_storeu_si128((__m128i*)destination, mem); + //check if any of the characters is a terminating zero + __m128i res = _mm_cmpeq_epi8(mem, zero); + destination += 2; + if (_mm_movemask_epi8(res)) + break; + argument += 16; + } + } + } + else +#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY + { + PIXCopyEventArgumentSlow(destination, limit, argument); + } + } + else + { + *destination++ = 0ull; + } + } + } + + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument) + { + PIXCopyEventArgument(destination, limit, (PCSTR)argument); + } + + inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) + { + *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE); + while (destination < limit) + { + UINT64 c = static_cast(argument[0]); + if (!c) + { + *destination++ = 0; + return; + } + UINT64 x = c; + c = static_cast(argument[1]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 16; + c = static_cast(argument[2]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 32; + c = static_cast(argument[3]); + if (!c) + { + *destination++ = x; + return; + } + x |= c << 48; + *destination++ = x; + argument += 4; + } + } + + inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) + { +#if PIX_ENABLE_BLOCK_ARGUMENT_COPY + if (PIXIsPointerAligned<8>(argument)) + { + *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE); + UINT64* source = (UINT64*)argument; + while (destination < limit) + { + UINT64 qword = *source++; + *destination++ = qword; + //check if any of the characters is a terminating zero + //TODO: check if reversed condition is faster + if (!((qword & 0xFFFF000000000000) && + (qword & 0xFFFF00000000) && + (qword & 0xFFFF0000) && + (qword & 0xFFFF))) + { + break; + } + } + } + else +#endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY + { + PIXCopyEventArgumentSlowest(destination, limit, argument); + } + } + + template<> + inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument) + { + if (destination < limit) + { + if (argument != nullptr) + { +#if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY + if (PIXIsPointerAligned<16>(argument)) + { + *destination++ = PIXEncodeStringInfo(0, 16, FALSE, FALSE); + __m128i zero = _mm_setzero_si128(); + if (PIXIsPointerAligned<16>(destination)) + { + while (destination < limit) + { + __m128i mem = _mm_load_si128((__m128i*)argument); + _mm_store_si128((__m128i*)destination, mem); + //check if any of the characters is a terminating zero + __m128i res = _mm_cmpeq_epi16(mem, zero); + destination += 2; + if (_mm_movemask_epi8(res)) + break; + argument += 8; + } + } + else + { + while (destination < limit) + { + __m128i mem = _mm_load_si128((__m128i*)argument); + _mm_storeu_si128((__m128i*)destination, mem); + //check if any of the characters is a terminating zero + __m128i res = _mm_cmpeq_epi16(mem, zero); + destination += 2; + if (_mm_movemask_epi8(res)) + break; + argument += 8; + } + } + } + else +#endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY + { + PIXCopyEventArgumentSlow(destination, limit, argument); + } + } + else + { + *destination++ = 0ull; + } + } + } + + inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit) + { + // nothing + UNREFERENCED_PARAMETER(destination); + UNREFERENCED_PARAMETER(limit); + } + + template + void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args) + { + PIXCopyEventArgument(destination, limit, arg); + PIXCopyEventArguments(destination, limit, args...); + } + + template + 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 + UINT64* EncodeBeginEventForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args) + { + UINT64* destination = buffer; + UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords; + + *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuBeginOnContext()); + *destination++ = color; + + PIXCopyEventArguments(destination, limit, formatString, args...); + *destination = 0ull; + + return destination; + } + + template + UINT64* EncodeSetMarkerForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args) + { + UINT64* destination = buffer; + UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords; + + *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer::GpuSetMarkerOnContext()); + *destination++ = color; + + PIXCopyEventArguments(destination, limit, formatString, args...); + *destination = 0ull; + + return destination; + } +} + +#endif //_PIXEventsLegacy_H_ diff --git a/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/pix3.h b/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/pix3.h new file mode 100644 index 000000000..13126c400 --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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 + +#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_ diff --git a/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/pix3_win.h b/Backends/Graphics5/Direct3D12/pix/Include/WinPixEventRuntime/pix3_win.h new file mode 100644 index 000000000..121c40cb1 --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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(time.QuadPart); +} + +enum PIXHUDOptions +{ + PIX_HUD_SHOW_ON_ALL_WINDOWS = 0x1, + PIX_HUD_SHOW_ON_TARGET_WINDOW_ONLY = 0x2, + PIX_HUD_SHOW_ON_NO_WINDOWS = 0x4 +}; +DEFINE_ENUM_FLAG_OPERATORS(PIXHUDOptions); + +#if defined(USE_PIX_SUPPORTED_ARCHITECTURE) && defined(USE_PIX) + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) + +#include +#include +#include +#include + +#define PIXERRORCHECK(value) do { \ + if (FAILED(value)) \ + return nullptr; \ + } while(0) + +namespace PixImpl +{ +#ifndef PIX3_WIN_UNIT_TEST + + __forceinline BOOL GetModuleHandleExW( + DWORD dwFlags, + LPCWSTR lpModuleName, + HMODULE* phModule) + { + return ::GetModuleHandleExW(dwFlags, lpModuleName, phModule); + } + + __forceinline HRESULT SHGetKnownFolderPath( + REFKNOWNFOLDERID rfid, + DWORD dwFlags, + HANDLE hToken, + PWSTR* ppszPath) + { + return ::SHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); + } + + __forceinline void CoTaskMemFree(LPVOID pv) + { + return ::CoTaskMemFree(pv); + } + + __forceinline HANDLE FindFirstFileW( + LPCWSTR lpFileName, + LPWIN32_FIND_DATAW lpFindFileData) + { + return ::FindFirstFileW(lpFileName, lpFindFileData); + } + + __forceinline DWORD GetFileAttributesW(LPCWSTR lpFileName) + { + return ::GetFileAttributesW(lpFileName); + } + + __forceinline BOOL FindNextFileW( + HANDLE hFindFile, + LPWIN32_FIND_DATAW lpFindFileData) + { + return ::FindNextFileW(hFindFile, lpFindFileData); + } + + __forceinline BOOL FindClose(HANDLE hFindFile) + { + return ::FindClose(hFindFile); + } + + __forceinline HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, DWORD flags) + { + return ::LoadLibraryExW(lpLibFileName, NULL, flags); + } + +#endif // !PIX3_WIN_UNIT_TESTS + + __forceinline void * GetGpuCaptureFunctionPtr(LPCSTR fnName) noexcept + { + HMODULE module = GetModuleHandleW(L"WinPixGpuCapturer.dll"); + if (module == NULL) + { + return nullptr; + } + + auto fn = (void*)GetProcAddress(module, fnName); + if (fn == nullptr) + { + return nullptr; + } + + return fn; + } + + __forceinline void* GetTimingCaptureFunctionPtr(LPCSTR fnName) noexcept + { + HMODULE module = GetModuleHandleW(L"WinPixTimingCapturer.dll"); + if (module == NULL) + { + return nullptr; + } + + auto fn = (void*)GetProcAddress(module, fnName); + if (fn == nullptr) + { + return nullptr; + } + + return fn; + } + + __forceinline HMODULE PIXLoadLatestCapturerLibrary(wchar_t const* capturerDllName, DWORD flags) + { + HMODULE libHandle{}; + + if (PixImpl::GetModuleHandleExW(0, capturerDllName, &libHandle)) + { + return libHandle; + } + + LPWSTR programFilesPath = nullptr; + if (FAILED(PixImpl::SHGetKnownFolderPath(FOLDERID_ProgramFiles, KF_FLAG_DEFAULT, NULL, &programFilesPath))) + { + PixImpl::CoTaskMemFree(programFilesPath); + return nullptr; + } + + wchar_t pixSearchPath[MAX_PATH]; + + if (FAILED(StringCchCopyW(pixSearchPath, MAX_PATH, programFilesPath))) + { + PixImpl::CoTaskMemFree(programFilesPath); + return nullptr; + } + PixImpl::CoTaskMemFree(programFilesPath); + + PIXERRORCHECK(StringCchCatW(pixSearchPath, MAX_PATH, L"\\Microsoft PIX\\*")); + + WIN32_FIND_DATAW findData; + bool foundPixInstallation = false; + wchar_t newestVersionFound[MAX_PATH]; + wchar_t output[MAX_PATH]; + wchar_t possibleOutput[MAX_PATH]; + + HANDLE hFind = PixImpl::FindFirstFileW(pixSearchPath, &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + if (((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) && + (findData.cFileName[0] != '.')) + { + if (!foundPixInstallation || wcscmp(newestVersionFound, findData.cFileName) <= 0) + { + // length - 1 to get rid of the wildcard character in the search path + PIXERRORCHECK(StringCchCopyNW(possibleOutput, MAX_PATH, pixSearchPath, wcslen(pixSearchPath) - 1)); + PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, findData.cFileName)); + PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, L"\\")); + PIXERRORCHECK(StringCchCatW(possibleOutput, MAX_PATH, capturerDllName)); + + DWORD result = PixImpl::GetFileAttributesW(possibleOutput); + + if (result != INVALID_FILE_ATTRIBUTES && !(result & FILE_ATTRIBUTE_DIRECTORY)) + { + foundPixInstallation = true; + PIXERRORCHECK(StringCchCopyW(newestVersionFound, _countof(newestVersionFound), findData.cFileName)); + PIXERRORCHECK(StringCchCopyW(output, _countof(possibleOutput), possibleOutput)); + } + } + } + } while (PixImpl::FindNextFileW(hFind, &findData) != 0); + } + + PixImpl::FindClose(hFind); + + if (!foundPixInstallation) + { + SetLastError(ERROR_FILE_NOT_FOUND); + return nullptr; + } + + return PixImpl::LoadLibraryExW(output, flags); + } +} + +#undef PIXERRORCHECK + +__forceinline HMODULE PIXLoadLatestWinPixGpuCapturerLibrary() +{ + return PixImpl::PIXLoadLatestCapturerLibrary( + L"WinPixGpuCapturer.dll", + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); +} + +__forceinline HMODULE PIXLoadLatestWinPixTimingCapturerLibrary() +{ + return PixImpl::PIXLoadLatestCapturerLibrary( + L"WinPixTimingCapturer.dll", + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); +} + +__forceinline HRESULT WINAPI PIXSetTargetWindow(HWND hwnd) +{ + typedef void(WINAPI* SetGlobalTargetWindowFn)(HWND); + + auto fn = (SetGlobalTargetWindowFn)PixImpl::GetGpuCaptureFunctionPtr("SetGlobalTargetWindow"); + if (fn == nullptr) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + fn(hwnd); + return S_OK; +} + +__forceinline HRESULT WINAPI PIXGpuCaptureNextFrames(PCWSTR fileName, UINT32 numFrames) +{ + typedef HRESULT(WINAPI* CaptureNextFrameFn)(PCWSTR, UINT32); + + auto fn = (CaptureNextFrameFn)PixImpl::GetGpuCaptureFunctionPtr("CaptureNextFrame"); + if (fn == nullptr) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + return fn(fileName, numFrames); +} + +extern "C" __forceinline HRESULT WINAPI PIXBeginCapture2(DWORD captureFlags, _In_opt_ const PPIXCaptureParameters captureParameters) +{ + if (captureFlags == PIX_CAPTURE_GPU) + { + typedef HRESULT(WINAPI* BeginProgrammaticGpuCaptureFn)(const PPIXCaptureParameters); + + auto fn = (BeginProgrammaticGpuCaptureFn)PixImpl::GetGpuCaptureFunctionPtr("BeginProgrammaticGpuCapture"); + if (fn == nullptr) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + return fn(captureParameters); + } + else if (captureFlags == PIX_CAPTURE_TIMING) + { + typedef HRESULT(WINAPI* BeginProgrammaticTimingCaptureFn)(void const*, UINT64); + + auto fn = (BeginProgrammaticTimingCaptureFn)PixImpl::GetTimingCaptureFunctionPtr("BeginProgrammaticTimingCapture"); + if (fn == nullptr) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + return fn(&captureParameters->TimingCaptureParameters, sizeof(captureParameters->TimingCaptureParameters)); + } + else + { + return E_NOTIMPL; + } +} + +extern "C" __forceinline HRESULT WINAPI PIXEndCapture(BOOL discard) +{ + // 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_ diff --git a/Backends/Graphics5/Direct3D12/pix/ThirdPartyNotices.txt b/Backends/Graphics5/Direct3D12/pix/ThirdPartyNotices.txt new file mode 100644 index 000000000..90ad07dc9 --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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 +================================== \ No newline at end of file diff --git a/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.dll b/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.dll new file mode 100644 index 000000000..5d86359db Binary files /dev/null and b/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.dll differ diff --git a/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.lib b/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.lib new file mode 100644 index 000000000..7a909a872 Binary files /dev/null and b/Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime.lib differ diff --git a/Backends/Graphics5/Direct3D12/pix/license.txt b/Backends/Graphics5/Direct3D12/pix/license.txt new file mode 100644 index 000000000..44378268b --- /dev/null +++ b/Backends/Graphics5/Direct3D12/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. \ No newline at end of file diff --git a/kfile.js b/kfile.js index f65199d99..bf9f0d698 100644 --- a/kfile.js +++ b/kfile.js @@ -184,6 +184,12 @@ if (platform === Platform.Windows) { else { throw new Error('VR API ' + vr + ' is not available for Windows.'); } + + if (Options.pix) { + project.addDefine('KOPE_PIX'); + project.addIncludeDir('Backends/Graphics5/Direct3D12/pix/Include'); + project.addLib('Backends/Graphics5/Direct3D12/pix/bin/x64/WinPixEventRuntime'); + } } else if (platform === Platform.WindowsApp) { g4 = true;