From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- gfx/angle/checkout/src/common/debug.h | 468 ++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 gfx/angle/checkout/src/common/debug.h (limited to 'gfx/angle/checkout/src/common/debug.h') diff --git a/gfx/angle/checkout/src/common/debug.h b/gfx/angle/checkout/src/common/debug.h new file mode 100644 index 0000000000..a9ee795103 --- /dev/null +++ b/gfx/angle/checkout/src/common/debug.h @@ -0,0 +1,468 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// debug.h: Debugging utilities. A lot of the logging code is adapted from Chromium's +// base/logging.h. + +#ifndef COMMON_DEBUG_H_ +#define COMMON_DEBUG_H_ + +#include +#include + +#include +#include +#include +#include +#include + +#include "common/angleutils.h" +#include "common/entry_points_enum_autogen.h" +#include "common/platform.h" + +#if defined(ANGLE_PLATFORM_WINDOWS) +# include +typedef unsigned long DWORD; +typedef _Return_type_success_(return >= 0) long HRESULT; +#endif + +#if !defined(TRACE_OUTPUT_FILE) +# define TRACE_OUTPUT_FILE "angle_debug.txt" +#endif + +namespace gl +{ +class Context; + +// Pairs a begin event with an end event. +class [[nodiscard]] ScopedPerfEventHelper : angle::NonCopyable +{ + public: + ScopedPerfEventHelper(Context *context, angle::EntryPoint entryPoint); + ~ScopedPerfEventHelper(); + ANGLE_FORMAT_PRINTF(2, 3) + void begin(const char *format, ...); + + private: + gl::Context *mContext; + const angle::EntryPoint mEntryPoint; + const char *mFunctionName; + bool mCalledBeginEvent; +}; + +using LogSeverity = int; +// Note: the log severities are used to index into the array of names, +// see g_logSeverityNames. +constexpr LogSeverity LOG_EVENT = 0; +constexpr LogSeverity LOG_INFO = 1; +constexpr LogSeverity LOG_WARN = 2; +constexpr LogSeverity LOG_ERR = 3; +constexpr LogSeverity LOG_FATAL = 4; +constexpr LogSeverity LOG_NUM_SEVERITIES = 5; + +void Trace(LogSeverity severity, const char *message); + +// This class more or less represents a particular log message. You +// create an instance of LogMessage and then stream stuff to it. +// When you finish streaming to it, ~LogMessage is called and the +// full message gets streamed to the appropriate destination. +// +// You shouldn't actually use LogMessage's constructor to log things, +// though. You should use the ERR() and WARN() macros. +class LogMessage : angle::NonCopyable +{ + public: + // Used for ANGLE_LOG(severity). + LogMessage(const char *file, const char *function, int line, LogSeverity severity); + ~LogMessage(); + std::ostream &stream() { return mStream; } + + LogSeverity getSeverity() const; + std::string getMessage() const; + + private: + const char *mFile; + const char *mFunction; + const int mLine; + const LogSeverity mSeverity; + + std::ostringstream mStream; +}; + +// Wraps the API/Platform-specific debug annotation functions. +// Also handles redirecting logging destination. +class DebugAnnotator : angle::NonCopyable +{ + public: + DebugAnnotator() {} + virtual ~DebugAnnotator() {} + virtual void beginEvent(gl::Context *context, + angle::EntryPoint entryPoint, + const char *eventName, + const char *eventMessage) = 0; + virtual void endEvent(gl::Context *context, + const char *eventName, + angle::EntryPoint entryPoint) = 0; + virtual void setMarker(gl::Context *context, const char *markerName) = 0; + virtual bool getStatus(const gl::Context *context) = 0; + // Log Message Handler that gets passed every log message, + // when debug annotations are initialized, + // replacing default handling by LogMessage. + virtual void logMessage(const LogMessage &msg) const = 0; +}; + +bool ShouldBeginScopedEvent(const gl::Context *context); +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator); +void UninitializeDebugAnnotations(); +bool DebugAnnotationsActive(const gl::Context *context); +bool DebugAnnotationsInitialized(); + +void InitializeDebugMutexIfNeeded(); + +std::mutex &GetDebugMutex(); + +namespace priv +{ +// This class is used to explicitly ignore values in the conditional logging macros. This avoids +// compiler warnings like "value computed is not used" and "statement has no effect". +class LogMessageVoidify +{ + public: + LogMessageVoidify() {} + // This has to be an operator with a precedence lower than << but higher than ?: + void operator&(std::ostream &) {} +}; + +extern std::ostream *gSwallowStream; + +// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments. +bool ShouldCreatePlatformLogMessage(LogSeverity severity); + +// N is the width of the output to the stream. The output is padded with zeros +// if value is less than N characters. +// S is the stream type, either ostream for ANSI or wostream for wide character. +// T is the type of the value to output to the stream. +// C is the type of characters - either char for ANSI or wchar_t for wide char. +template +S &FmtHex(S &stream, T value, const C *zeroX, C zero) +{ + stream << zeroX; + + std::ios_base::fmtflags oldFlags = stream.flags(); + std::streamsize oldWidth = stream.width(); + typename S::char_type oldFill = stream.fill(); + + stream << std::hex << std::uppercase << std::setw(N) << std::setfill(zero) << value; + + stream.flags(oldFlags); + stream.width(oldWidth); + stream.fill(oldFill); + + return stream; +} + +template +S &FmtHexAutoSized(S &stream, T value, const C *prefix, const C *zeroX, C zero) +{ + if (prefix) + { + stream << prefix; + } + + constexpr int N = sizeof(T) * 2; + return priv::FmtHex(stream, value, zeroX, zero); +} + +template +class FmtHexHelper +{ + public: + FmtHexHelper(const C *prefix, T value) : mPrefix(prefix), mValue(value) {} + explicit FmtHexHelper(T value) : mPrefix(nullptr), mValue(value) {} + + private: + const C *mPrefix; + T mValue; + + friend std::ostream &operator<<(std::ostream &os, const FmtHexHelper &fmt) + { + return FmtHexAutoSized(os, fmt.mValue, fmt.mPrefix, "0x", '0'); + } + + friend std::wostream &operator<<(std::wostream &wos, const FmtHexHelper &fmt) + { + return FmtHexAutoSized(wos, fmt.mValue, fmt.mPrefix, L"0x", L'0'); + } +}; + +} // namespace priv + +template +priv::FmtHexHelper FmtHex(T value) +{ + return priv::FmtHexHelper(value); +} + +#if defined(ANGLE_PLATFORM_WINDOWS) +priv::FmtHexHelper FmtHR(HRESULT value); +priv::FmtHexHelper FmtErr(DWORD value); +#endif // defined(ANGLE_PLATFORM_WINDOWS) + +template +std::ostream &FmtHex(std::ostream &os, T value) +{ + return priv::FmtHexAutoSized(os, value, "", "0x", '0'); +} + +// A few definitions of macros that don't generate much code. These are used +// by ANGLE_LOG(). Since these are used all over our code, it's +// better to have compact code for these operations. +#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \ + ::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__) +#define COMPACT_ANGLE_LOG_EX_INFO(ClassName, ...) \ + ::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_INFO, ##__VA_ARGS__) +#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \ + ::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__) +#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \ + ::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__) +#define COMPACT_ANGLE_LOG_EX_FATAL(ClassName, ...) \ + ::gl::ClassName(__FILE__, __FUNCTION__, __LINE__, ::gl::LOG_FATAL, ##__VA_ARGS__) + +#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage) +#define COMPACT_ANGLE_LOG_INFO COMPACT_ANGLE_LOG_EX_INFO(LogMessage) +#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage) +#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage) +#define COMPACT_ANGLE_LOG_FATAL COMPACT_ANGLE_LOG_EX_FATAL(LogMessage) + +#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity)) + +// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold. +// Condition is evaluated once and only once. +#define ANGLE_LAZY_STREAM(stream, condition) \ + !(condition) ? static_cast(0) : ::gl::priv::LogMessageVoidify() & (stream) + +// We use the preprocessor's merging operator, "##", so that, e.g., +// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT. There's some funny +// subtle difference between ostream member streaming functions (e.g., +// ostream::operator<<(int) and ostream non-member streaming functions +// (e.g., ::operator<<(ostream&, string&): it turns out that it's +// impossible to stream something like a string directly to an unnamed +// ostream. We employ a neat hack by calling the stream() member +// function of LogMessage which seems to avoid the problem. +#define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream() + +#define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity)) + +} // namespace gl + +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) +# define ANGLE_TRACE_ENABLED +#endif + +#if !defined(NDEBUG) || defined(ANGLE_ASSERT_ALWAYS_ON) +# define ANGLE_ENABLE_ASSERTS +#endif + +#define INFO() ANGLE_LOG(INFO) +#define WARN() ANGLE_LOG(WARN) +#define ERR() ANGLE_LOG(ERR) +#define FATAL() ANGLE_LOG(FATAL) + +// A macro to log a performance event around a scope. +#if defined(ANGLE_TRACE_ENABLED) +# if defined(_MSC_VER) +# define EVENT(context, entryPoint, message, ...) \ + gl::ScopedPerfEventHelper scopedPerfEventHelper##__LINE__( \ + context, angle::EntryPoint::entryPoint); \ + do \ + { \ + if (gl::ShouldBeginScopedEvent(context)) \ + { \ + scopedPerfEventHelper##__LINE__.begin( \ + "%s(" message ")", GetEntryPointName(angle::EntryPoint::entryPoint), \ + __VA_ARGS__); \ + } \ + } while (0) +# else +# define EVENT(context, entryPoint, message, ...) \ + gl::ScopedPerfEventHelper scopedPerfEventHelper(context, \ + angle::EntryPoint::entryPoint); \ + do \ + { \ + if (gl::ShouldBeginScopedEvent(context)) \ + { \ + scopedPerfEventHelper.begin("%s(" message ")", \ + GetEntryPointName(angle::EntryPoint::entryPoint), \ + ##__VA_ARGS__); \ + } \ + } while (0) +# endif // _MSC_VER +#else +# define EVENT(message, ...) (void(0)) +#endif + +// The state tracked by ANGLE will be validated with the driver state before each call +#if defined(ANGLE_ENABLE_DEBUG_TRACE) +# define ANGLE_STATE_VALIDATION_ENABLED +#endif + +#if defined(__GNUC__) +# define ANGLE_CRASH() __builtin_trap() +#else +# define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0)), __assume(0) +#endif + +#if !defined(NDEBUG) +# define ANGLE_ASSERT_IMPL(expression) assert(expression) +#else +// TODO(jmadill): Detect if debugger is attached and break. +# define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH() +#endif // !defined(NDEBUG) + +// Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an +// object with a non-trivial destructor (LogMessage). On MSVC x86 (checked on 2015 Update 3), this +// causes a few additional pointless instructions to be emitted even at full optimization level, +// even though the : arm of the ternary operator is clearly never executed. Using a simpler object +// to be &'d with Voidify() avoids these extra instructions. Using a simpler POD object with a +// templated operator<< also works to avoid these instructions. However, this causes warnings on +// statically defined implementations of operator<<(std::ostream, ...) in some .cpp files, because +// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an ostream* also is +// not suitable, because some compilers warn of undefined behavior. +#define ANGLE_EAT_STREAM_PARAMETERS \ + true ? static_cast(0) : ::gl::priv::LogMessageVoidify() & (*::gl::priv::gSwallowStream) + +// A macro asserting a condition and outputting failures to the debug log +#if defined(ANGLE_ENABLE_ASSERTS) +# define ASSERT(expression) \ + (expression ? static_cast(0) \ + : (FATAL() << "\t! Assert failed in " << __FUNCTION__ << " (" << __FILE__ \ + << ":" << __LINE__ << "): " << #expression)) +#else +# define ASSERT(condition) ANGLE_EAT_STREAM_PARAMETERS << !(condition) +#endif // defined(ANGLE_ENABLE_ASSERTS) + +#define ANGLE_UNUSED_VARIABLE(variable) (static_cast(variable)) + +// A macro to indicate unimplemented functionality +#ifndef NOASSERT_UNIMPLEMENTED +# define NOASSERT_UNIMPLEMENTED 1 +#endif + +#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS) +# define UNIMPLEMENTED() \ + do \ + { \ + WARN() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \ + << ")"; \ + ASSERT(NOASSERT_UNIMPLEMENTED); \ + } while (0) + +// A macro for code which is not expected to be reached under valid assumptions +# define UNREACHABLE() \ + do \ + { \ + FATAL() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" \ + << __LINE__ << ")"; \ + } while (0) +#else +# define UNIMPLEMENTED() \ + do \ + { \ + ASSERT(NOASSERT_UNIMPLEMENTED); \ + } while (0) + +// A macro for code which is not expected to be reached under valid assumptions +# define UNREACHABLE() \ + do \ + { \ + ASSERT(false); \ + } while (0) +#endif // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS) + +#if defined(ANGLE_PLATFORM_WINDOWS) +# define ANGLE_FUNCTION __FUNCTION__ +#else +# define ANGLE_FUNCTION __func__ +#endif + +// Defining ANGLE_ENABLE_STRUCT_PADDING_WARNINGS will enable warnings when members are added to +// structs to enforce packing. This is helpful for diagnosing unexpected struct sizes when making +// fast cache variables. +#if defined(__clang__) +# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic error \"-Wpadded\"") +# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("clang diagnostic pop") +#elif defined(__GNUC__) +# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic error \"-Wpadded\"") +# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \ + __pragma(warning(push)) __pragma(warning(error : 4820)) +# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS __pragma(warning(pop)) +#else +# define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS +# define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_SUGGEST_OVERRIDE_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wsuggest-destructor-override\"") \ + _Pragma("clang diagnostic ignored \"-Wsuggest-override\"") +# define ANGLE_REENABLE_SUGGEST_OVERRIDE_WARNINGS _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_SUGGEST_OVERRIDE_WARNINGS +# define ANGLE_REENABLE_SUGGEST_OVERRIDE_WARNINGS +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_EXTRA_SEMI_WARNING \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wextra-semi\"") +# define ANGLE_REENABLE_EXTRA_SEMI_WARNING _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_EXTRA_SEMI_WARNING +# define ANGLE_REENABLE_EXTRA_SEMI_WARNING +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_EXTRA_SEMI_STMT_WARNING \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wextra-semi-stmt\"") +# define ANGLE_REENABLE_EXTRA_SEMI_STMT_WARNING _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_EXTRA_SEMI_STMT_WARNING +# define ANGLE_REENABLE_EXTRA_SEMI_STMT_WARNING +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_SHADOWING_WARNING \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow-field\"") +# define ANGLE_REENABLE_SHADOWING_WARNING _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_SHADOWING_WARNING +# define ANGLE_REENABLE_SHADOWING_WARNING +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winconsistent-missing-destructor-override\"") +# define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING +# define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING +#endif + +#if defined(__clang__) +# define ANGLE_DISABLE_UNUSED_FUNCTION_WARNING \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-function\"") +# define ANGLE_REENABLE_UNUSED_FUNCTION_WARNING _Pragma("clang diagnostic pop") +#else +# define ANGLE_DISABLE_UNUSED_FUNCTION_WARNING +# define ANGLE_REENABLE_UNUSED_FUNCTION_WARNING +#endif + +#endif // COMMON_DEBUG_H_ -- cgit v1.2.3