| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- // Copyright (c) Microsoft Corporation.
- // Licensed under the MIT License.
- // Don't include this file directly - use pix3.h
- // This file encodes PIX events in the legacy PIX event format.
- #ifndef _PIXEventsLegacy_H_
- #define _PIXEventsLegacy_H_
- #include <cstdint>
- #if defined(_M_X64) || defined(_M_IX86)
- #include <emmintrin.h>
- #endif
- namespace PixEventsLegacy
- {
- enum PIXEventType
- {
- PIXEvent_EndEvent = 0x000,
- PIXEvent_BeginEvent_VarArgs = 0x001,
- PIXEvent_BeginEvent_NoArgs = 0x002,
- PIXEvent_SetMarker_VarArgs = 0x007,
- PIXEvent_SetMarker_NoArgs = 0x008,
- PIXEvent_EndEvent_OnContext = 0x010,
- PIXEvent_BeginEvent_OnContext_VarArgs = 0x011,
- PIXEvent_BeginEvent_OnContext_NoArgs = 0x012,
- PIXEvent_SetMarker_OnContext_VarArgs = 0x017,
- PIXEvent_SetMarker_OnContext_NoArgs = 0x018,
- };
- static const UINT64 PIXEventsReservedRecordSpaceQwords = 64;
- static const UINT64 PIXEventsReservedTailSpaceQwords = 2;
- static const UINT64 PIXEventsSafeFastCopySpaceQwords = PIXEventsReservedRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
- static const UINT64 PIXEventsGraphicsRecordSpaceQwords = 64;
- //Bits 7-19 (13 bits)
- static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80;
- //Bits 10-19 (10 bits)
- static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00;
- static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF;
- static const UINT64 PIXEventsTypeBitShift = 10;
- //Bits 20-63 (44 bits)
- static const UINT64 PIXEventsTimestampReadMask = 0xFFFFFFFFFFF00000;
- static const UINT64 PIXEventsTimestampWriteMask = 0x00000FFFFFFFFFFF;
- static const UINT64 PIXEventsTimestampBitShift = 20;
- inline UINT64 PIXEncodeEventInfo(UINT64 timestamp, PIXEventType eventType)
- {
- return ((timestamp & PIXEventsTimestampWriteMask) << PIXEventsTimestampBitShift) |
- (((UINT64)eventType & PIXEventsTypeWriteMask) << PIXEventsTypeBitShift);
- }
- //Bits 60-63 (4)
- static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F;
- static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000;
- static const UINT64 PIXEventsStringAlignmentBitShift = 60;
- //Bits 55-59 (5)
- static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F;
- static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000;
- static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55;
- //Bit 54
- static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001;
- static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000;
- static const UINT64 PIXEventsStringIsANSIBitShift = 54;
- //Bit 53
- static const UINT64 PIXEventsStringIsShortcutWriteMask = 0x0000000000000001;
- static const UINT64 PIXEventsStringIsShortcutReadMask = 0x0020000000000000;
- static const UINT64 PIXEventsStringIsShortcutBitShift = 53;
- inline UINT64 PIXEncodeStringInfo(UINT64 alignment, UINT64 copyChunkSize, BOOL isANSI, BOOL isShortcut)
- {
- return ((alignment & PIXEventsStringAlignmentWriteMask) << PIXEventsStringAlignmentBitShift) |
- ((copyChunkSize & PIXEventsStringCopyChunkSizeWriteMask) << PIXEventsStringCopyChunkSizeBitShift) |
- (((UINT64)isANSI & PIXEventsStringIsANSIWriteMask) << PIXEventsStringIsANSIBitShift) |
- (((UINT64)isShortcut & PIXEventsStringIsShortcutWriteMask) << PIXEventsStringIsShortcutBitShift);
- }
- template<UINT alignment, class T>
- inline bool PIXIsPointerAligned(T* pointer)
- {
- return !(((UINT64)pointer) & (alignment - 1));
- }
- // Generic template version slower because of the additional clear write
- template<class T>
- inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument)
- {
- if (destination < limit)
- {
- *destination = 0ull;
- *((T*)destination) = argument;
- ++destination;
- }
- }
- // int32 specialization to avoid slower double memory writes
- template<>
- inline void PIXCopyEventArgument<INT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT32 argument)
- {
- if (destination < limit)
- {
- *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
- ++destination;
- }
- }
- // unsigned int32 specialization to avoid slower double memory writes
- template<>
- inline void PIXCopyEventArgument<UINT32>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT32 argument)
- {
- if (destination < limit)
- {
- *destination = static_cast<UINT64>(argument);
- ++destination;
- }
- }
- // int64 specialization to avoid slower double memory writes
- template<>
- inline void PIXCopyEventArgument<INT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, INT64 argument)
- {
- if (destination < limit)
- {
- *reinterpret_cast<INT64*>(destination) = argument;
- ++destination;
- }
- }
- // unsigned int64 specialization to avoid slower double memory writes
- template<>
- inline void PIXCopyEventArgument<UINT64>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, UINT64 argument)
- {
- if (destination < limit)
- {
- *destination = argument;
- ++destination;
- }
- }
- //floats must be cast to double during writing the data to be properly printed later when reading the data
- //this is needed because when float is passed to varargs function it's cast to double
- template<>
- inline void PIXCopyEventArgument<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument)
- {
- if (destination < limit)
- {
- *reinterpret_cast<double*>(destination) = static_cast<double>(argument);
- ++destination;
- }
- }
- //char has to be cast to a longer signed integer type
- //this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
- template<>
- inline void PIXCopyEventArgument<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument)
- {
- if (destination < limit)
- {
- *reinterpret_cast<INT64*>(destination) = static_cast<INT64>(argument);
- ++destination;
- }
- }
- //unsigned char has to be cast to a longer unsigned integer type
- //this is due to printf not ignoring correctly the upper bits of unsigned long long for a char format specifier
- template<>
- inline void PIXCopyEventArgument<unsigned char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument)
- {
- if (destination < limit)
- {
- *destination = static_cast<UINT64>(argument);
- ++destination;
- }
- }
- //bool has to be cast to an integer since it's not explicitly supported by string format routines
- //there's no format specifier for bool type, but it should work with integer format specifiers
- template<>
- inline void PIXCopyEventArgument<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument)
- {
- if (destination < limit)
- {
- *destination = static_cast<UINT64>(argument);
- ++destination;
- }
- }
- inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
- {
- *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
- while (destination < limit)
- {
- UINT64 c = static_cast<uint8_t>(argument[0]);
- if (!c)
- {
- *destination++ = 0;
- return;
- }
- UINT64 x = c;
- c = static_cast<uint8_t>(argument[1]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 8;
- c = static_cast<uint8_t>(argument[2]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 16;
- c = static_cast<uint8_t>(argument[3]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 24;
- c = static_cast<uint8_t>(argument[4]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 32;
- c = static_cast<uint8_t>(argument[5]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 40;
- c = static_cast<uint8_t>(argument[6]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 48;
- c = static_cast<uint8_t>(argument[7]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 56;
- *destination++ = x;
- argument += 8;
- }
- }
- inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
- {
- #if PIX_ENABLE_BLOCK_ARGUMENT_COPY
- if (PIXIsPointerAligned<8>(argument))
- {
- *destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE);
- UINT64* source = (UINT64*)argument;
- while (destination < limit)
- {
- UINT64 qword = *source++;
- *destination++ = qword;
- //check if any of the characters is a terminating zero
- if (!((qword & 0xFF00000000000000) &&
- (qword & 0xFF000000000000) &&
- (qword & 0xFF0000000000) &&
- (qword & 0xFF00000000) &&
- (qword & 0xFF000000) &&
- (qword & 0xFF0000) &&
- (qword & 0xFF00) &&
- (qword & 0xFF)))
- {
- break;
- }
- }
- }
- else
- #endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
- {
- PIXCopyEventArgumentSlowest(destination, limit, argument);
- }
- }
- template<>
- inline void PIXCopyEventArgument<PCSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCSTR argument)
- {
- if (destination < limit)
- {
- if (argument != nullptr)
- {
- #if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
- if (PIXIsPointerAligned<16>(argument))
- {
- *destination++ = PIXEncodeStringInfo(0, 16, TRUE, FALSE);
- __m128i zero = _mm_setzero_si128();
- if (PIXIsPointerAligned<16>(destination))
- {
- while (destination < limit)
- {
- __m128i mem = _mm_load_si128((__m128i*)argument);
- _mm_store_si128((__m128i*)destination, mem);
- //check if any of the characters is a terminating zero
- __m128i res = _mm_cmpeq_epi8(mem, zero);
- destination += 2;
- if (_mm_movemask_epi8(res))
- break;
- argument += 16;
- }
- }
- else
- {
- while (destination < limit)
- {
- __m128i mem = _mm_load_si128((__m128i*)argument);
- _mm_storeu_si128((__m128i*)destination, mem);
- //check if any of the characters is a terminating zero
- __m128i res = _mm_cmpeq_epi8(mem, zero);
- destination += 2;
- if (_mm_movemask_epi8(res))
- break;
- argument += 16;
- }
- }
- }
- else
- #endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
- {
- PIXCopyEventArgumentSlow(destination, limit, argument);
- }
- }
- else
- {
- *destination++ = 0ull;
- }
- }
- }
- template<>
- inline void PIXCopyEventArgument<PSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PSTR argument)
- {
- PIXCopyEventArgument(destination, limit, (PCSTR)argument);
- }
- inline void PIXCopyEventArgumentSlowest(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
- {
- *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
- while (destination < limit)
- {
- UINT64 c = static_cast<uint16_t>(argument[0]);
- if (!c)
- {
- *destination++ = 0;
- return;
- }
- UINT64 x = c;
- c = static_cast<uint16_t>(argument[1]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 16;
- c = static_cast<uint16_t>(argument[2]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 32;
- c = static_cast<uint16_t>(argument[3]);
- if (!c)
- {
- *destination++ = x;
- return;
- }
- x |= c << 48;
- *destination++ = x;
- argument += 4;
- }
- }
- inline void PIXCopyEventArgumentSlow(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
- {
- #if PIX_ENABLE_BLOCK_ARGUMENT_COPY
- if (PIXIsPointerAligned<8>(argument))
- {
- *destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE);
- UINT64* source = (UINT64*)argument;
- while (destination < limit)
- {
- UINT64 qword = *source++;
- *destination++ = qword;
- //check if any of the characters is a terminating zero
- //TODO: check if reversed condition is faster
- if (!((qword & 0xFFFF000000000000) &&
- (qword & 0xFFFF00000000) &&
- (qword & 0xFFFF0000) &&
- (qword & 0xFFFF)))
- {
- break;
- }
- }
- }
- else
- #endif // PIX_ENABLE_BLOCK_ARGUMENT_COPY
- {
- PIXCopyEventArgumentSlowest(destination, limit, argument);
- }
- }
- template<>
- inline void PIXCopyEventArgument<PCWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PCWSTR argument)
- {
- if (destination < limit)
- {
- if (argument != nullptr)
- {
- #if (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
- if (PIXIsPointerAligned<16>(argument))
- {
- *destination++ = PIXEncodeStringInfo(0, 16, FALSE, FALSE);
- __m128i zero = _mm_setzero_si128();
- if (PIXIsPointerAligned<16>(destination))
- {
- while (destination < limit)
- {
- __m128i mem = _mm_load_si128((__m128i*)argument);
- _mm_store_si128((__m128i*)destination, mem);
- //check if any of the characters is a terminating zero
- __m128i res = _mm_cmpeq_epi16(mem, zero);
- destination += 2;
- if (_mm_movemask_epi8(res))
- break;
- argument += 8;
- }
- }
- else
- {
- while (destination < limit)
- {
- __m128i mem = _mm_load_si128((__m128i*)argument);
- _mm_storeu_si128((__m128i*)destination, mem);
- //check if any of the characters is a terminating zero
- __m128i res = _mm_cmpeq_epi16(mem, zero);
- destination += 2;
- if (_mm_movemask_epi8(res))
- break;
- argument += 8;
- }
- }
- }
- else
- #endif // (defined(_M_X64) || defined(_M_IX86)) && PIX_ENABLE_BLOCK_ARGUMENT_COPY
- {
- PIXCopyEventArgumentSlow(destination, limit, argument);
- }
- }
- else
- {
- *destination++ = 0ull;
- }
- }
- }
- inline void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit)
- {
- // nothing
- UNREFERENCED_PARAMETER(destination);
- UNREFERENCED_PARAMETER(limit);
- }
- template<typename ARG, typename... ARGS>
- void PIXCopyEventArguments(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, ARG const& arg, ARGS const&... args)
- {
- PIXCopyEventArgument(destination, limit, arg);
- PIXCopyEventArguments(destination, limit, args...);
- }
- template<typename... ARGS>
- struct PIXEventTypeInferer
- {
- static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_VarArgs; }
- static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_VarArgs; }
- static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
- static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
- static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
- // Xbox and Windows store different types of events for context events.
- // On Xbox these include a context argument, while on Windows they do
- // not. It is important not to change the event types used on the
- // Windows version as there are OS components (eg debug layer & DRED)
- // that decode event structs.
- #ifdef PIX_XBOX
- static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_VarArgs; }
- static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_VarArgs; }
- static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
- #else
- static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_VarArgs; }
- static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_VarArgs; }
- static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
- #endif
- };
- template<>
- struct PIXEventTypeInferer<>
- {
- static constexpr PIXEventType Begin() { return PIXEvent_BeginEvent_NoArgs; }
- static constexpr PIXEventType SetMarker() { return PIXEvent_SetMarker_NoArgs; }
- static constexpr PIXEventType BeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
- static constexpr PIXEventType SetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
- static constexpr PIXEventType End() { return PIXEvent_EndEvent; }
- #ifdef PIX_XBOX
- static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_OnContext_NoArgs; }
- static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_OnContext_NoArgs; }
- static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent_OnContext; }
- #else
- static constexpr PIXEventType GpuBeginOnContext() { return PIXEvent_BeginEvent_NoArgs; }
- static constexpr PIXEventType GpuSetMarkerOnContext() { return PIXEvent_SetMarker_NoArgs; }
- static constexpr PIXEventType GpuEndOnContext() { return PIXEvent_EndEvent; }
- #endif
- };
- template<size_t size, typename STR, typename... ARGS>
- UINT64* EncodeBeginEventForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
- {
- UINT64* destination = buffer;
- UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
- *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuBeginOnContext());
- *destination++ = color;
- PIXCopyEventArguments(destination, limit, formatString, args...);
- *destination = 0ull;
- return destination;
- }
- template<size_t size, typename STR, typename... ARGS>
- UINT64* EncodeSetMarkerForContext(UINT64 (&buffer)[size], UINT64 color, STR formatString, ARGS... args)
- {
- UINT64* destination = buffer;
- UINT64* limit = buffer + PIXEventsGraphicsRecordSpaceQwords - PIXEventsReservedTailSpaceQwords;
- *destination++ = PIXEncodeEventInfo(0, PIXEventTypeInferer<ARGS...>::GpuSetMarkerOnContext());
- *destination++ = color;
- PIXCopyEventArguments(destination, limit, formatString, args...);
- *destination = 0ull;
- return destination;
- }
- }
- #endif //_PIXEventsLegacy_H_
|