|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
|
|
#ifndef _PIXEventsCommon_H_ |
|
|
#define _PIXEventsCommon_H_ |
|
|
|
|
|
#if defined(_AMD64_) || defined(_X86_) |
|
|
#include <emmintrin.h> |
|
|
#endif |
|
|
|
|
|
extern "C" UINT64 WINAPI PIXEventsReplaceBlock(bool getEarliestTime); |
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
static const UINT64 PIXEventsBlockEndMarker = 0x00000000000FFF80; |
|
|
|
|
|
|
|
|
static const UINT64 PIXEventsTypeReadMask = 0x00000000000FFC00; |
|
|
static const UINT64 PIXEventsTypeWriteMask = 0x00000000000003FF; |
|
|
static const UINT64 PIXEventsTypeBitShift = 10; |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
static const UINT64 PIXEventsStringAlignmentWriteMask = 0x000000000000000F; |
|
|
static const UINT64 PIXEventsStringAlignmentReadMask = 0xF000000000000000; |
|
|
static const UINT64 PIXEventsStringAlignmentBitShift = 60; |
|
|
|
|
|
|
|
|
static const UINT64 PIXEventsStringCopyChunkSizeWriteMask = 0x000000000000001F; |
|
|
static const UINT64 PIXEventsStringCopyChunkSizeReadMask = 0x0F80000000000000; |
|
|
static const UINT64 PIXEventsStringCopyChunkSizeBitShift = 55; |
|
|
|
|
|
|
|
|
static const UINT64 PIXEventsStringIsANSIWriteMask = 0x0000000000000001; |
|
|
static const UINT64 PIXEventsStringIsANSIReadMask = 0x0040000000000000; |
|
|
static const UINT64 PIXEventsStringIsANSIBitShift = 54; |
|
|
|
|
|
|
|
|
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)); |
|
|
} |
|
|
|
|
|
template<class T> |
|
|
inline void PIXCopyEventArgument(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, T argument) |
|
|
{ |
|
|
if (destination < limit) |
|
|
{ |
|
|
*((T*)destination) = argument; |
|
|
++destination; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
inline void PIXCopyEventArgument<float>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, float argument) |
|
|
{ |
|
|
if (destination < limit) |
|
|
{ |
|
|
*((double*)destination) = (double)(argument); |
|
|
++destination; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
inline void PIXCopyEventArgument<char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, char argument) |
|
|
{ |
|
|
if (destination < limit) |
|
|
{ |
|
|
*((INT64*)destination) = (INT64)(argument); |
|
|
++destination; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
inline void PIXCopyEventArgument<unsigned char>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, unsigned char argument) |
|
|
{ |
|
|
if (destination < limit) |
|
|
{ |
|
|
*destination = (UINT64)(argument); |
|
|
++destination; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
inline void PIXCopyEventArgument<bool>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, bool argument) |
|
|
{ |
|
|
if (destination < limit) |
|
|
{ |
|
|
*destination = (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 = argument[0]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = 0; |
|
|
return; |
|
|
} |
|
|
UINT64 x = c; |
|
|
c = argument[1]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 8; |
|
|
c = argument[2]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 16; |
|
|
c = argument[3]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 24; |
|
|
c = argument[4]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 32; |
|
|
c = argument[5]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 40; |
|
|
c = argument[6]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 48; |
|
|
c = 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 (PIXIsPointerAligned<8>(argument)) |
|
|
{ |
|
|
*destination++ = PIXEncodeStringInfo(0, 8, TRUE, FALSE); |
|
|
UINT64* source = (UINT64*)argument; |
|
|
while (destination < limit) |
|
|
{ |
|
|
UINT64 qword = *source++; |
|
|
*destination++ = qword; |
|
|
|
|
|
if (!((qword & 0xFF00000000000000) && |
|
|
(qword & 0xFF000000000000) && |
|
|
(qword & 0xFF0000000000) && |
|
|
(qword & 0xFF00000000) && |
|
|
(qword & 0xFF000000) && |
|
|
(qword & 0xFF0000) && |
|
|
(qword & 0xFF00) && |
|
|
(qword & 0xFF))) |
|
|
{ |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
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(_AMD64_) || defined(_X86_) |
|
|
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); |
|
|
|
|
|
__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); |
|
|
|
|
|
__m128i res = _mm_cmpeq_epi8(mem, zero); |
|
|
destination += 2; |
|
|
if (_mm_movemask_epi8(res)) |
|
|
break; |
|
|
argument += 16; |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
#endif |
|
|
{ |
|
|
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 = argument[0]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = 0; |
|
|
return; |
|
|
} |
|
|
UINT64 x = c; |
|
|
c = argument[1]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 16; |
|
|
c = argument[2]; |
|
|
if (!c) |
|
|
{ |
|
|
*destination++ = x; |
|
|
return; |
|
|
} |
|
|
x |= c << 32; |
|
|
c = 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 (PIXIsPointerAligned<8>(argument)) |
|
|
{ |
|
|
*destination++ = PIXEncodeStringInfo(0, 8, FALSE, FALSE); |
|
|
UINT64* source = (UINT64*)argument; |
|
|
while (destination < limit) |
|
|
{ |
|
|
UINT64 qword = *source++; |
|
|
*destination++ = qword; |
|
|
|
|
|
|
|
|
if (!((qword & 0xFFFF000000000000) && |
|
|
(qword & 0xFFFF00000000) && |
|
|
(qword & 0xFFFF0000) && |
|
|
(qword & 0xFFFF))) |
|
|
{ |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
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(_AMD64_) || defined(_X86_) |
|
|
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); |
|
|
|
|
|
__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); |
|
|
|
|
|
__m128i res = _mm_cmpeq_epi16(mem, zero); |
|
|
destination += 2; |
|
|
if (_mm_movemask_epi8(res)) |
|
|
break; |
|
|
argument += 8; |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
#endif |
|
|
{ |
|
|
PIXCopyEventArgumentSlow(destination, limit, argument); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
*destination++ = 0ull; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
template<> |
|
|
inline void PIXCopyEventArgument<PWSTR>(_Out_writes_to_ptr_(limit) UINT64*& destination, _In_ const UINT64* limit, _In_ PWSTR argument) |
|
|
{ |
|
|
PIXCopyEventArgument(destination, limit, (PCWSTR)argument); |
|
|
}; |
|
|
|
|
|
#if defined(__d3d12_x_h__) || defined(__d3d12_h__) |
|
|
|
|
|
inline void PIXSetMarkerOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size) |
|
|
{ |
|
|
commandList->SetMarker(D3D12_EVENT_METADATA, data, size); |
|
|
} |
|
|
|
|
|
inline void PIXSetMarkerOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size) |
|
|
{ |
|
|
commandQueue->SetMarker(D3D12_EVENT_METADATA, data, size); |
|
|
} |
|
|
|
|
|
inline void PIXBeginEventOnContext(_In_ ID3D12GraphicsCommandList* commandList, _In_reads_bytes_(size) void* data, UINT size) |
|
|
{ |
|
|
commandList->BeginEvent(D3D12_EVENT_METADATA, data, size); |
|
|
} |
|
|
|
|
|
inline void PIXBeginEventOnContext(_In_ ID3D12CommandQueue* commandQueue, _In_reads_bytes_(size) void* data, UINT size) |
|
|
{ |
|
|
commandQueue->BeginEvent(D3D12_EVENT_METADATA, data, size); |
|
|
} |
|
|
inline void PIXEndEventOnContext(_In_ ID3D12GraphicsCommandList* commandList) |
|
|
{ |
|
|
commandList->EndEvent(); |
|
|
} |
|
|
|
|
|
inline void PIXEndEventOnContext(_In_ ID3D12CommandQueue* commandQueue) |
|
|
{ |
|
|
commandQueue->EndEvent(); |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
template<class T> struct PIXInferScopedEventType { typedef T Type; }; |
|
|
template<class T> struct PIXInferScopedEventType<const T> { typedef T Type; }; |
|
|
template<class T> struct PIXInferScopedEventType<T*> { typedef T Type; }; |
|
|
template<class T> struct PIXInferScopedEventType<T* const> { typedef T Type; }; |
|
|
template<> struct PIXInferScopedEventType<UINT64> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<const UINT64> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<INT64> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<const INT64> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<UINT> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<const UINT> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<INT> { typedef void Type; }; |
|
|
template<> struct PIXInferScopedEventType<const INT> { typedef void Type; }; |
|
|
#endif |
|
|
|