LiteFX 0.3.1.2022
Computer Graphics Engine
debug.hpp
1#pragma once
2
3#include <litefx/string.hpp>
4#include <litefx/math.hpp>
5#include <d3d12.h>
6#include <fmt/format.h>
7#include <array>
8#include <comdef.h>
9#include <wrl.h>
10
11using namespace Microsoft::WRL;
12
13#ifndef NDEBUG
14
15// Definitions as defined in WinPixEventRuntime
16#define D3D12_EVENT_METADATA 0x02
17
18#define EVENT_TIMESTAMP_WRITE_MASK 0x00000FFFFFFFFFFF
19#define EVENT_TYPE_WRITE_MASK 0x00000000000003FF
20#define EVENT_TIMESTAMP_BIT_SHIFT 20
21#define EVENT_TYPE_BIT_SHIFT 10
22#define EVENT_TYPE_END_EVENT 0x00
23#define EVENT_TYPE_BEGIN_EVENT_VARARGS 0x01
24#define EVENT_TYPE_BEGIN_EVENT_NOARGS 0x02
25
26consteval UInt64 EncodeEventInfo(UInt64 timestamp, UInt64 eventType)
27{
28 return ((timestamp & EVENT_TIMESTAMP_WRITE_MASK) << EVENT_TIMESTAMP_BIT_SHIFT) | ((eventType & EVENT_TYPE_WRITE_MASK) << EVENT_TYPE_BIT_SHIFT);
29}
30
31#define EVENT_STRING_ALIGNMENT_WRITE_MASK 0x000000000000000F
32#define EVENT_STRING_ALIGNMENT_BIT_SHIFT 60
33#define EVENT_STRING_COPY_CHUNK_SIZE_WRITE_MASK 0x000000000000001F
34#define EVENT_STRING_COPY_CHUNK_SIZE_BIT_SHIFT 55
35#define EVENT_STRING_IS_ANSI_WRITE_MASK 0x0000000000000001
36#define EVENT_STRING_IS_ANSI_BIT_SHIFT 54
37#define EVENT_STRING_IS_SHORTCUT_WRITE_MASK 0x0000000000000001
38#define EVENT_STRING_IS_SHORTCUT_BIT_SHIFT 53
39
40consteval UInt64 EncodeStringInfo(UInt64 alignment, UInt64 copyChunkSize, BOOL isANSI, BOOL isShortcut)
41{
42 return ((alignment & EVENT_STRING_ALIGNMENT_WRITE_MASK) << EVENT_STRING_ALIGNMENT_BIT_SHIFT) | ((copyChunkSize & EVENT_STRING_COPY_CHUNK_SIZE_WRITE_MASK) << EVENT_STRING_COPY_CHUNK_SIZE_BIT_SHIFT) |
43 ((static_cast<UInt64>(isANSI) & EVENT_STRING_IS_ANSI_WRITE_MASK) << EVENT_STRING_IS_ANSI_BIT_SHIFT) | ((static_cast<UInt64>(isShortcut) & EVENT_STRING_IS_SHORTCUT_WRITE_MASK) << EVENT_STRING_IS_SHORTCUT_BIT_SHIFT);
44}
45
46static void CopyEventName(const String str, UInt64*& buffer, UInt64* end)
47{
48 *buffer++ = ::EncodeStringInfo(0, 8, FALSE, FALSE);
49 auto argument = str.c_str();
50
51 while (buffer < end)
52 {
53 UInt64 c = static_cast<UInt16>(argument[0]);
54 if (!c)
55 {
56 *buffer++ = 0;
57 return;
58 }
59
60 UInt64 x = c;
61 c = static_cast<UInt16>(argument[1]);
62
63 if (!c)
64 {
65 *buffer++ = x;
66 return;
67 }
68
69 x |= c << 16;
70 c = static_cast<UInt16>(argument[2]);
71
72 if (!c)
73 {
74 *buffer++ = x;
75 return;
76 }
77
78 x |= c << 32;
79 c = static_cast<UInt16>(argument[3]);
80
81 if (!c)
82 {
83 *buffer++ = x;
84 return;
85 }
86
87 x |= c << 48;
88 *buffer++ = x;
89 argument += 4;
90 }
91}
92
93template <typename... TArgs>
94static void inline BeginEvent(ID3D12CommandQueue* queue, UInt64 color, StringView format, TArgs... args)
95{
96 std::array<UInt64, 64> buffer {};
97 buffer[0] = ::EncodeEventInfo(0, EVENT_TYPE_BEGIN_EVENT_NOARGS);
98 buffer[1] = color;
99 UInt64* destination = &buffer[2];
100 UInt64* limit = destination + 62;
101
102 // Format the string.
103 String str = fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
104 ::CopyEventName(str, destination, limit);
105
106 // Issue the event.
107 queue->BeginEvent(D3D12_EVENT_METADATA, static_cast<void*>(buffer.data()), static_cast<UInt32>(reinterpret_cast<Byte*>(destination) - reinterpret_cast<Byte*>(buffer.data())));
108}
109
110template <typename... TArgs>
111static void inline BeginEvent(const ComPtr<ID3D12CommandQueue>& queue, UInt64 color, StringView format, TArgs... args)
112{
113 ::BeginEvent(queue.Get(), color, format, args...);
114}
115
116template <typename... TArgs>
117static void inline BeginEvent(ID3D12CommandQueue* queue, StringView format, TArgs... args)
118{
119 ::BeginEvent(queue, 0xDBDBDBFF, format, args...);
120}
121
122template <typename... TArgs>
123static void inline BeginEvent(const ComPtr<ID3D12CommandQueue>& queue, StringView format, TArgs... args)
124{
125 ::BeginEvent(queue.Get(), 0xDBDBDBFF, format, args...);
126}
127
128static void inline EndEvent(ID3D12CommandQueue* queue)
129{
130 queue->EndEvent();
131}
132
133static void inline EndEvent(const ComPtr<ID3D12CommandQueue>& queue)
134{
135 queue->EndEvent();
136}
137
138#undef D3D12_EVENT_METADATA
139#undef EVENT_TIMESTAMP_WRITE_MASK
140#undef EVENT_TYPE_WRITE_MASK
141#undef EVENT_TIMESTAMP_BIT_SHIFT
142#undef EVENT_TYPE_WRITE_BIT_SHIFT
143#undef EVENT_TYPE_END_EVENT
144#undef EVENT_TYPE_BEGIN_EVENT_VARARGS
145#undef EVENT_TYPE_BEGIN_EVENT_NOARGS
146#undef EVENT_STRING_ALIGNMENT_WRITE_MASK
147#undef EVENT_STRING_ALIGNMENT_BIT_SHIFT
148#undef EVENT_STRING_COPY_CHUNK_SIZE_WRITE_MASK
149#undef EVENT_STRING_COPY_CHUNK_SIZE_BIT_SHIFT
150#undef EVENT_STRING_IS_ANSI_WRITE_MASK
151#undef EVENT_STRING_IS_ANSI_BIT_SHIFT
152#undef EVENT_STRING_IS_SHORTCUT_WRITE_MASK
153#undef EVENT_STRING_IS_SHORTCUT_BIT_SHIFT
154
155#else
156
157template <typename... TArgs>
158static void inline BeginEvent(ID3D12CommandQueue* /*queue*/, UInt64 /*color*/, StringView /*format*/, TArgs... /*args*/)
159{
160}
161
162template <typename... TArgs>
163static void inline BeginEvent(const ComPtr<ID3D12CommandQueue>& /*queue*/, UInt64 /*color*/, StringView /*format*/, TArgs... /*args*/)
164{
165}
166
167template <typename... TArgs>
168static void inline BeginEvent(ID3D12CommandQueue* /*queue*/, StringView /*format*/, TArgs... /*args*/)
169{
170}
171
172template <typename... TArgs>
173static void inline BeginEvent(const ComPtr<ID3D12CommandQueue>& /*queue*/, StringView format, TArgs... /*args*/)
174{
175}
176
177static void inline EndEvent(ID3D12CommandQueue* /*queue*/)
178{
179}
180
181static void inline EndEvent(const ComPtr<ID3D12CommandQueue>& /*queue*/)
182{
183}
184
185#endif
uint32_t UInt32
Definition: math.hpp:37
uint16_t UInt16
Definition: math.hpp:35
uint64_t UInt64
Definition: math.hpp:39
uint8_t Byte
Definition: math.hpp:33
std::string String
Definition: string.hpp:19
auto format(LiteFX::Platform t, FormatContext &ctx) const
Definition: app_formatters.hpp:8