Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/common/debug.h
1693 views
1
//
2
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
7
// debug.h: Debugging utilities. A lot of the logging code is adapted from Chromium's
8
// base/logging.h.
9
10
#ifndef COMMON_DEBUG_H_
11
#define COMMON_DEBUG_H_
12
13
#include <assert.h>
14
#include <stdio.h>
15
16
#include <iomanip>
17
#include <ios>
18
#include <mutex>
19
#include <sstream>
20
#include <string>
21
22
#include "common/angleutils.h"
23
#include "common/entry_points_enum_autogen.h"
24
#include "common/platform.h"
25
26
#if !defined(TRACE_OUTPUT_FILE)
27
# define TRACE_OUTPUT_FILE "angle_debug.txt"
28
#endif
29
30
namespace gl
31
{
32
class Context;
33
34
// Pairs a D3D begin event with an end event.
35
class ScopedPerfEventHelper : angle::NonCopyable
36
{
37
public:
38
ScopedPerfEventHelper(Context *context, angle::EntryPoint entryPoint);
39
~ScopedPerfEventHelper();
40
ANGLE_FORMAT_PRINTF(2, 3)
41
void begin(const char *format, ...);
42
43
private:
44
gl::Context *mContext;
45
const angle::EntryPoint mEntryPoint;
46
const char *mFunctionName;
47
bool mCalledBeginEvent;
48
};
49
50
using LogSeverity = int;
51
// Note: the log severities are used to index into the array of names,
52
// see g_logSeverityNames.
53
constexpr LogSeverity LOG_EVENT = 0;
54
constexpr LogSeverity LOG_INFO = 1;
55
constexpr LogSeverity LOG_WARN = 2;
56
constexpr LogSeverity LOG_ERR = 3;
57
constexpr LogSeverity LOG_FATAL = 4;
58
constexpr LogSeverity LOG_NUM_SEVERITIES = 5;
59
60
void Trace(LogSeverity severity, const char *message);
61
62
// This class more or less represents a particular log message. You
63
// create an instance of LogMessage and then stream stuff to it.
64
// When you finish streaming to it, ~LogMessage is called and the
65
// full message gets streamed to the appropriate destination.
66
//
67
// You shouldn't actually use LogMessage's constructor to log things,
68
// though. You should use the ERR() and WARN() macros.
69
class LogMessage : angle::NonCopyable
70
{
71
public:
72
// Used for ANGLE_LOG(severity).
73
LogMessage(const char *file, const char *function, int line, LogSeverity severity);
74
~LogMessage();
75
std::ostream &stream() { return mStream; }
76
77
LogSeverity getSeverity() const;
78
std::string getMessage() const;
79
80
private:
81
const char *mFile;
82
const char *mFunction;
83
const int mLine;
84
const LogSeverity mSeverity;
85
86
std::ostringstream mStream;
87
};
88
89
// Wraps the API/Platform-specific debug annotation functions.
90
// Also handles redirecting logging destination.
91
class DebugAnnotator : angle::NonCopyable
92
{
93
public:
94
DebugAnnotator() {}
95
virtual ~DebugAnnotator() {}
96
virtual void beginEvent(gl::Context *context,
97
angle::EntryPoint entryPoint,
98
const char *eventName,
99
const char *eventMessage) = 0;
100
virtual void endEvent(gl::Context *context,
101
const char *eventName,
102
angle::EntryPoint entryPoint) = 0;
103
virtual void setMarker(const char *markerName) = 0;
104
virtual bool getStatus() = 0;
105
// Log Message Handler that gets passed every log message,
106
// when debug annotations are initialized,
107
// replacing default handling by LogMessage.
108
virtual void logMessage(const LogMessage &msg) const = 0;
109
};
110
111
bool ShouldBeginScopedEvent();
112
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
113
void UninitializeDebugAnnotations();
114
bool DebugAnnotationsActive();
115
bool DebugAnnotationsInitialized();
116
117
void InitializeDebugMutexIfNeeded();
118
119
std::mutex &GetDebugMutex();
120
121
namespace priv
122
{
123
// This class is used to explicitly ignore values in the conditional logging macros. This avoids
124
// compiler warnings like "value computed is not used" and "statement has no effect".
125
class LogMessageVoidify
126
{
127
public:
128
LogMessageVoidify() {}
129
// This has to be an operator with a precedence lower than << but higher than ?:
130
void operator&(std::ostream &) {}
131
};
132
133
extern std::ostream *gSwallowStream;
134
135
// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
136
bool ShouldCreatePlatformLogMessage(LogSeverity severity);
137
138
template <int N, typename T>
139
std::ostream &FmtHex(std::ostream &os, T value)
140
{
141
os << "0x";
142
143
std::ios_base::fmtflags oldFlags = os.flags();
144
std::streamsize oldWidth = os.width();
145
std::ostream::char_type oldFill = os.fill();
146
147
os << std::hex << std::uppercase << std::setw(N) << std::setfill('0') << value;
148
149
os.flags(oldFlags);
150
os.width(oldWidth);
151
os.fill(oldFill);
152
153
return os;
154
}
155
156
template <typename T>
157
std::ostream &FmtHexAutoSized(std::ostream &os, T value)
158
{
159
constexpr int N = sizeof(T) * 2;
160
return priv::FmtHex<N>(os, value);
161
}
162
163
template <typename T>
164
class FmtHexHelper
165
{
166
public:
167
FmtHexHelper(const char *prefix, T value) : mPrefix(prefix), mValue(value) {}
168
explicit FmtHexHelper(T value) : mPrefix(nullptr), mValue(value) {}
169
170
private:
171
const char *mPrefix;
172
T mValue;
173
174
friend std::ostream &operator<<(std::ostream &os, const FmtHexHelper &fmt)
175
{
176
if (fmt.mPrefix)
177
{
178
os << fmt.mPrefix;
179
}
180
return FmtHexAutoSized(os, fmt.mValue);
181
}
182
};
183
184
} // namespace priv
185
186
template <typename T>
187
priv::FmtHexHelper<T> FmtHex(T value)
188
{
189
return priv::FmtHexHelper<T>(value);
190
}
191
192
#if defined(ANGLE_PLATFORM_WINDOWS)
193
priv::FmtHexHelper<HRESULT> FmtHR(HRESULT value);
194
priv::FmtHexHelper<DWORD> FmtErr(DWORD value);
195
#endif // defined(ANGLE_PLATFORM_WINDOWS)
196
197
template <typename T>
198
std::ostream &FmtHex(std::ostream &os, T value)
199
{
200
return priv::FmtHexAutoSized(os, value);
201
}
202
203
// A few definitions of macros that don't generate much code. These are used
204
// by ANGLE_LOG(). Since these are used all over our code, it's
205
// better to have compact code for these operations.
206
#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \
207
::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__)
208
#define COMPACT_ANGLE_LOG_EX_INFO(ClassName, ...) \
209
::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_INFO, ##__VA_ARGS__)
210
#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \
211
::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
212
#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
213
::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
214
#define COMPACT_ANGLE_LOG_EX_FATAL(ClassName, ...) \
215
::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_FATAL, ##__VA_ARGS__)
216
217
#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
218
#define COMPACT_ANGLE_LOG_INFO COMPACT_ANGLE_LOG_EX_INFO(LogMessage)
219
#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
220
#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
221
#define COMPACT_ANGLE_LOG_FATAL COMPACT_ANGLE_LOG_EX_FATAL(LogMessage)
222
223
#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
224
225
// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
226
// Condition is evaluated once and only once.
227
#define ANGLE_LAZY_STREAM(stream, condition) \
228
!(condition) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (stream)
229
230
// We use the preprocessor's merging operator, "##", so that, e.g.,
231
// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT. There's some funny
232
// subtle difference between ostream member streaming functions (e.g.,
233
// ostream::operator<<(int) and ostream non-member streaming functions
234
// (e.g., ::operator<<(ostream&, string&): it turns out that it's
235
// impossible to stream something like a string directly to an unnamed
236
// ostream. We employ a neat hack by calling the stream() member
237
// function of LogMessage which seems to avoid the problem.
238
#define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream()
239
240
#define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity))
241
242
} // namespace gl
243
244
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
245
# define ANGLE_TRACE_ENABLED
246
#endif
247
248
#if !defined(NDEBUG) || defined(ANGLE_ASSERT_ALWAYS_ON)
249
# define ANGLE_ENABLE_ASSERTS
250
#endif
251
252
#define INFO() ANGLE_LOG(INFO)
253
#define WARN() ANGLE_LOG(WARN)
254
#define ERR() ANGLE_LOG(ERR)
255
#define FATAL() ANGLE_LOG(FATAL)
256
257
// A macro to log a performance event around a scope.
258
#if defined(ANGLE_TRACE_ENABLED)
259
# if defined(_MSC_VER)
260
# define EVENT(context, entryPoint, message, ...) \
261
gl::ScopedPerfEventHelper scopedPerfEventHelper##__LINE__( \
262
context, angle::EntryPoint::entryPoint); \
263
do \
264
{ \
265
if (gl::ShouldBeginScopedEvent()) \
266
{ \
267
scopedPerfEventHelper##__LINE__.begin( \
268
"%s(" message ")", GetEntryPointName(angle::EntryPoint::entryPoint), \
269
__VA_ARGS__); \
270
} \
271
} while (0)
272
# else
273
# define EVENT(context, entryPoint, message, ...) \
274
gl::ScopedPerfEventHelper scopedPerfEventHelper(context, \
275
angle::EntryPoint::entryPoint); \
276
do \
277
{ \
278
if (gl::ShouldBeginScopedEvent()) \
279
{ \
280
scopedPerfEventHelper.begin("%s(" message ")", \
281
GetEntryPointName(angle::EntryPoint::entryPoint), \
282
##__VA_ARGS__); \
283
} \
284
} while (0)
285
# endif // _MSC_VER
286
#else
287
# define EVENT(message, ...) (void(0))
288
#endif
289
290
// The state tracked by ANGLE will be validated with the driver state before each call
291
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
292
# define ANGLE_STATE_VALIDATION_ENABLED
293
#endif
294
295
#if defined(__GNUC__)
296
# define ANGLE_CRASH() __builtin_trap()
297
#else
298
# define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0)), __assume(0)
299
#endif
300
301
#if !defined(NDEBUG)
302
# define ANGLE_ASSERT_IMPL(expression) assert(expression)
303
#else
304
// TODO(jmadill): Detect if debugger is attached and break.
305
# define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
306
#endif // !defined(NDEBUG)
307
308
// Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an
309
// object with a non-trivial destructor (LogMessage). On MSVC x86 (checked on 2015 Update 3), this
310
// causes a few additional pointless instructions to be emitted even at full optimization level,
311
// even though the : arm of the ternary operator is clearly never executed. Using a simpler object
312
// to be &'d with Voidify() avoids these extra instructions. Using a simpler POD object with a
313
// templated operator<< also works to avoid these instructions. However, this causes warnings on
314
// statically defined implementations of operator<<(std::ostream, ...) in some .cpp files, because
315
// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an ostream* also is
316
// not suitable, because some compilers warn of undefined behavior.
317
#define ANGLE_EAT_STREAM_PARAMETERS \
318
true ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (*::gl::priv::gSwallowStream)
319
320
// A macro asserting a condition and outputting failures to the debug log
321
#if defined(ANGLE_ENABLE_ASSERTS)
322
# define ASSERT(expression) \
323
(expression ? static_cast<void>(0) \
324
: (FATAL() << "\t! Assert failed in " << __FUNCTION__ << " (" << __FILE__ \
325
<< ":" << __LINE__ << "): " << #expression))
326
#else
327
# define ASSERT(condition) ANGLE_EAT_STREAM_PARAMETERS << !(condition)
328
#endif // defined(ANGLE_ENABLE_ASSERTS)
329
330
#define UNREACHABLE_IS_NORETURN 0
331
332
#define ANGLE_UNUSED_VARIABLE(variable) (static_cast<void>(variable))
333
334
// A macro to indicate unimplemented functionality
335
#ifndef NOASSERT_UNIMPLEMENTED
336
# define NOASSERT_UNIMPLEMENTED 1
337
#endif
338
339
#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
340
# define UNIMPLEMENTED() \
341
do \
342
{ \
343
WARN() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
344
<< ")"; \
345
ASSERT(NOASSERT_UNIMPLEMENTED); \
346
} while (0)
347
348
// A macro for code which is not expected to be reached under valid assumptions
349
# define UNREACHABLE() \
350
do \
351
{ \
352
FATAL() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" \
353
<< __LINE__ << ")"; \
354
} while (0)
355
#else
356
# define UNIMPLEMENTED() \
357
do \
358
{ \
359
ASSERT(NOASSERT_UNIMPLEMENTED); \
360
} while (0)
361
362
// A macro for code which is not expected to be reached under valid assumptions
363
# define UNREACHABLE() \
364
do \
365
{ \
366
ASSERT(false); \
367
} while (0)
368
#endif // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
369
370
#if defined(ANGLE_PLATFORM_WINDOWS)
371
# define ANGLE_FUNCTION __FUNCTION__
372
#else
373
# define ANGLE_FUNCTION __func__
374
#endif
375
376
// Defining ANGLE_ENABLE_STRUCT_PADDING_WARNINGS will enable warnings when members are added to
377
// structs to enforce packing. This is helpful for diagnosing unexpected struct sizes when making
378
// fast cache variables.
379
#if defined(__clang__)
380
# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
381
_Pragma("clang diagnostic push") _Pragma("clang diagnostic error \"-Wpadded\"")
382
# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("clang diagnostic pop")
383
#elif defined(__GNUC__)
384
# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
385
_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic error \"-Wpadded\"")
386
# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("GCC diagnostic pop")
387
#elif defined(_MSC_VER)
388
# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
389
__pragma(warning(push)) __pragma(warning(error : 4820))
390
# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS __pragma(warning(pop))
391
#else
392
# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
393
# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
394
#endif
395
396
#if defined(__clang__)
397
# define ANGLE_DISABLE_SUGGEST_OVERRIDE_WARNINGS \
398
_Pragma("clang diagnostic push") \
399
_Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \
400
_Pragma("clang diagnostic ignored \"-Wsuggest-override\"")
401
# define ANGLE_REENABLE_SUGGEST_OVERRIDE_WARNINGS _Pragma("clang diagnostic pop")
402
#else
403
# define ANGLE_DISABLE_SUGGEST_OVERRIDE_WARNINGS
404
# define ANGLE_REENABLE_SUGGEST_OVERRIDE_WARNINGS
405
#endif
406
407
#if defined(__clang__)
408
# define ANGLE_DISABLE_EXTRA_SEMI_WARNING \
409
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wextra-semi\"")
410
# define ANGLE_REENABLE_EXTRA_SEMI_WARNING _Pragma("clang diagnostic pop")
411
#else
412
# define ANGLE_DISABLE_EXTRA_SEMI_WARNING
413
# define ANGLE_REENABLE_EXTRA_SEMI_WARNING
414
#endif
415
416
#if defined(__clang__)
417
# define ANGLE_DISABLE_EXTRA_SEMI_STMT_WARNING \
418
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wextra-semi-stmt\"")
419
# define ANGLE_REENABLE_EXTRA_SEMI_STMT_WARNING _Pragma("clang diagnostic pop")
420
#else
421
# define ANGLE_DISABLE_EXTRA_SEMI_STMT_WARNING
422
# define ANGLE_REENABLE_EXTRA_SEMI_STMT_WARNING
423
#endif
424
425
#if defined(__clang__)
426
# define ANGLE_DISABLE_SHADOWING_WARNING \
427
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow-field\"")
428
# define ANGLE_REENABLE_SHADOWING_WARNING _Pragma("clang diagnostic pop")
429
#else
430
# define ANGLE_DISABLE_SHADOWING_WARNING
431
# define ANGLE_REENABLE_SHADOWING_WARNING
432
#endif
433
434
#if defined(__clang__)
435
# define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING \
436
_Pragma("clang diagnostic push") \
437
_Pragma("clang diagnostic ignored \"-Winconsistent-missing-destructor-override\"")
438
# define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING _Pragma("clang diagnostic pop")
439
#else
440
# define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING
441
# define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING
442
#endif
443
444
#if defined(__clang__)
445
# define ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING \
446
_Pragma("clang diagnostic push") \
447
_Pragma("clang diagnostic ignored \"-Wweak-template-vtables\"")
448
# define ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING _Pragma("clang diagnostic pop")
449
#else
450
# define ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING
451
# define ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING
452
#endif
453
454
#if defined(__clang__)
455
# define ANGLE_DISABLE_UNUSED_FUNCTION_WARNING \
456
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-function\"")
457
# define ANGLE_REENABLE_UNUSED_FUNCTION_WARNING _Pragma("clang diagnostic pop")
458
#else
459
# define ANGLE_DISABLE_UNUSED_FUNCTION_WARNING
460
# define ANGLE_REENABLE_UNUSED_FUNCTION_WARNING
461
#endif
462
463
#endif // COMMON_DEBUG_H_
464
465