mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
logs.hpp: refactoring (logs::message)
Make .error/.warning/... callable objects which can be pointed to. Make .always() more hard to access. Memory layout optimizations.
This commit is contained in:
parent
1d0f6eebdc
commit
04cac6cd33
@ -70,7 +70,7 @@ namespace vk
|
||||
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties);
|
||||
get_physical_device_features(allow_extensions);
|
||||
|
||||
rsx_log.always("Found vulkan-compatible GPU: '%s' running on driver %s", get_name(), get_driver_version());
|
||||
rsx_log.always()("Found vulkan-compatible GPU: '%s' running on driver %s", get_name(), get_driver_version());
|
||||
|
||||
if (get_driver_vendor() == driver_vendor::RADV && get_name().find("LLVM 8.0.0") != umax)
|
||||
{
|
||||
|
@ -187,7 +187,7 @@ struct fatal_error_listener final : logs::listener
|
||||
|
||||
void log(u64 /*stamp*/, const logs::message& msg, const std::string& prefix, const std::string& text) override
|
||||
{
|
||||
if (msg.sev == logs::level::fatal)
|
||||
if (msg == logs::level::fatal)
|
||||
{
|
||||
std::string _msg = "RPCS3: ";
|
||||
|
||||
@ -197,9 +197,9 @@ struct fatal_error_listener final : logs::listener
|
||||
_msg += ": ";
|
||||
}
|
||||
|
||||
if (msg.ch && '\0' != *msg.ch->name)
|
||||
if (msg->name && '\0' != *msg->name)
|
||||
{
|
||||
_msg += msg.ch->name;
|
||||
_msg += msg->name;
|
||||
_msg += ": ";
|
||||
}
|
||||
|
||||
@ -446,31 +446,19 @@ int main(int argc, char** argv)
|
||||
|
||||
{
|
||||
// Write RPCS3 version
|
||||
logs::stored_message ver;
|
||||
ver.m.ch = nullptr;
|
||||
ver.m.sev = logs::level::always;
|
||||
ver.stamp = 0;
|
||||
logs::stored_message ver{sys_log.always()};
|
||||
ver.text = fmt::format("RPCS3 v%s | %s", rpcs3::get_version().to_string(), rpcs3::get_branch());
|
||||
|
||||
// Write System information
|
||||
logs::stored_message sys;
|
||||
sys.m.ch = nullptr;
|
||||
sys.m.sev = logs::level::always;
|
||||
sys.stamp = 0;
|
||||
logs::stored_message sys{sys_log.always()};
|
||||
sys.text = utils::get_system_info();
|
||||
|
||||
// Write OS version
|
||||
logs::stored_message os;
|
||||
os.m.ch = nullptr;
|
||||
os.m.sev = logs::level::always;
|
||||
os.stamp = 0;
|
||||
logs::stored_message os{sys_log.always()};
|
||||
os.text = utils::get_OS_version();
|
||||
|
||||
// Write Qt version
|
||||
logs::stored_message qt;
|
||||
qt.m.ch = nullptr;
|
||||
qt.m.sev = (strcmp(QT_VERSION_STR, qVersion()) != 0) ? logs::level::error : logs::level::notice;
|
||||
qt.stamp = 0;
|
||||
logs::stored_message qt{(strcmp(QT_VERSION_STR, qVersion()) != 0) ? sys_log.error : sys_log.notice};
|
||||
qt.text = fmt::format("Qt version: Compiled against Qt %s | Run-time uses Qt %s", QT_VERSION_STR, qVersion());
|
||||
|
||||
logs::set_init({std::move(ver), std::move(sys), std::move(os), std::move(qt)});
|
||||
|
@ -43,7 +43,7 @@ void main_application::InitializeEmulator(const std::string& user, bool show_gui
|
||||
// Log Firmware Version after Emu was initialized
|
||||
const std::string firmware_version = utils::get_firmware_version();
|
||||
const std::string firmware_string = firmware_version.empty() ? "Missing Firmware" : ("Firmware version: " + firmware_version);
|
||||
sys_log.always("%s", firmware_string);
|
||||
sys_log.always()("%s", firmware_string);
|
||||
}
|
||||
|
||||
/** RPCS3 emulator has functions it desires to call from the GUI at times. Initialize them in here. */
|
||||
|
@ -254,7 +254,7 @@ void gui_settings::SaveCurrentConfig(const QString& config_name)
|
||||
|
||||
logs::level gui_settings::GetLogLevel() const
|
||||
{
|
||||
return logs::level{GetValue(gui::l_level).toUInt()};
|
||||
return logs::level(GetValue(gui::l_level).toUInt());
|
||||
}
|
||||
|
||||
bool gui_settings::GetGamelistColVisibility(int col) const
|
||||
|
@ -178,7 +178,7 @@ namespace gui
|
||||
const gui_save fs_dev_usb000_list = gui_save(fs, "dev_usb000_list", QStringList());
|
||||
|
||||
const gui_save l_tty = gui_save(logger, "TTY", true);
|
||||
const gui_save l_level = gui_save(logger, "level", static_cast<uint>(logs::level::success));
|
||||
const gui_save l_level = gui_save(logger, "level", static_cast<uchar>(logs::level::success));
|
||||
const gui_save l_prefix = gui_save(logger, "prefix_on", false);
|
||||
const gui_save l_stack = gui_save(logger, "stack", true);
|
||||
const gui_save l_stack_tty = gui_save(logger, "TTY_stack", false);
|
||||
|
@ -26,7 +26,7 @@ constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
struct gui_listener : logs::listener
|
||||
{
|
||||
atomic_t<logs::level> enabled{logs::level{UINT_MAX}};
|
||||
atomic_t<logs::level> enabled{logs::level{UCHAR_MAX}};
|
||||
|
||||
struct packet_t
|
||||
{
|
||||
@ -55,10 +55,10 @@ struct gui_listener : logs::listener
|
||||
{
|
||||
Q_UNUSED(stamp)
|
||||
|
||||
if (msg.sev <= enabled)
|
||||
if (msg <= enabled)
|
||||
{
|
||||
packet_t p,* _new = &p;
|
||||
_new->sev = msg.sev;
|
||||
_new->sev = msg;
|
||||
|
||||
if (show_prefix && !prefix.empty())
|
||||
{
|
||||
@ -67,12 +67,12 @@ struct gui_listener : logs::listener
|
||||
_new->msg += "} ";
|
||||
}
|
||||
|
||||
if (msg.ch && '\0' != *msg.ch->name)
|
||||
if (msg->name && '\0' != *msg->name)
|
||||
{
|
||||
_new->msg += msg.ch->name;
|
||||
_new->msg += msg.sev == logs::level::todo ? " TODO: " : ": ";
|
||||
_new->msg += msg->name;
|
||||
_new->msg += msg == logs::level::todo ? " TODO: " : ": ";
|
||||
}
|
||||
else if (msg.sev == logs::level::todo)
|
||||
else if (msg == logs::level::todo)
|
||||
{
|
||||
_new->msg += "TODO: ";
|
||||
}
|
||||
|
@ -65,6 +65,14 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||
|
||||
namespace logs
|
||||
{
|
||||
static_assert(std::is_empty_v<message> && sizeof(message) == 1);
|
||||
static_assert(sizeof(channel) == alignof(channel));
|
||||
static_assert(uchar(level::always) == 0);
|
||||
static_assert(uchar(level::fatal) == 1);
|
||||
static_assert(uchar(level::trace) == 7);
|
||||
static_assert((offsetof(channel, fatal) & 7) == 1);
|
||||
static_assert((offsetof(channel, trace) & 7) == 7);
|
||||
|
||||
// Memory-mapped buffer size
|
||||
constexpr u64 s_log_size = 32 * 1024 * 1024;
|
||||
|
||||
@ -618,7 +626,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
text.reserve(50000);
|
||||
|
||||
// Used character: U+00B7 (Middle Dot)
|
||||
switch (msg.sev)
|
||||
switch (msg)
|
||||
{
|
||||
case level::always: text = reinterpret_cast<const char*>(u8"·A "); break;
|
||||
case level::fatal: text = reinterpret_cast<const char*>(u8"·F "); break;
|
||||
@ -637,7 +645,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
const u64 frac = (stamp % 1'000'000);
|
||||
fmt::append(text, "%u:%02u:%02u.%06u ", hours, mins, secs, frac);
|
||||
|
||||
if (msg.ch == nullptr && stamp == 0)
|
||||
if (stamp == 0)
|
||||
{
|
||||
// Workaround for first special messages to keep backward compatibility
|
||||
text.clear();
|
||||
@ -650,12 +658,12 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||
text += "} ";
|
||||
}
|
||||
|
||||
if (msg.ch && '\0' != *msg.ch->name)
|
||||
if (msg->name && '\0' != *msg->name)
|
||||
{
|
||||
text += msg.ch->name;
|
||||
text += msg.sev == level::todo ? " TODO: " : ": ";
|
||||
text += msg->name;
|
||||
text += msg == level::todo ? " TODO: " : ": ";
|
||||
}
|
||||
else if (msg.sev == level::todo)
|
||||
else if (msg == level::todo)
|
||||
{
|
||||
text += "TODO: ";
|
||||
}
|
||||
|
@ -10,16 +10,16 @@
|
||||
|
||||
namespace logs
|
||||
{
|
||||
enum class level : unsigned
|
||||
enum class level : unsigned char
|
||||
{
|
||||
always, // Highest log severity (cannot be disabled)
|
||||
fatal,
|
||||
error,
|
||||
todo,
|
||||
success,
|
||||
warning,
|
||||
notice,
|
||||
trace, // Lowest severity (usually disabled)
|
||||
always = 0, // Highest log severity (cannot be disabled)
|
||||
fatal = 1,
|
||||
error = 2,
|
||||
todo = 3,
|
||||
success = 4,
|
||||
warning = 5,
|
||||
notice = 6,
|
||||
trace = 7, // Lowest severity (usually disabled)
|
||||
};
|
||||
|
||||
struct channel;
|
||||
@ -27,8 +27,27 @@ namespace logs
|
||||
// Message information
|
||||
struct message
|
||||
{
|
||||
channel* ch;
|
||||
level sev;
|
||||
// Default constructor
|
||||
consteval message() = default;
|
||||
|
||||
// Cannot be moved because it relies on its location
|
||||
message(const message&) = delete;
|
||||
|
||||
message& operator =(const message&) = delete;
|
||||
|
||||
// Send log message to the given channel with severity
|
||||
template <typename... Args>
|
||||
void operator()(const const_str& fmt, const Args&... args) const;
|
||||
|
||||
operator level() const
|
||||
{
|
||||
return level(reinterpret_cast<uptr>(this) & 7);
|
||||
}
|
||||
|
||||
const channel* operator->() const
|
||||
{
|
||||
return reinterpret_cast<const channel*>(reinterpret_cast<uptr>(this) & -16);
|
||||
}
|
||||
|
||||
private:
|
||||
// Send log message to global logger instance
|
||||
@ -39,7 +58,7 @@ namespace logs
|
||||
|
||||
struct stored_message
|
||||
{
|
||||
message m;
|
||||
const message& m;
|
||||
u64 stamp;
|
||||
std::string prefix;
|
||||
std::string text;
|
||||
@ -67,7 +86,7 @@ namespace logs
|
||||
void broadcast(const stored_message&) const;
|
||||
};
|
||||
|
||||
struct channel
|
||||
struct alignas(16) channel : private message
|
||||
{
|
||||
// Channel prefix (added to every log message)
|
||||
const char* const name;
|
||||
@ -76,31 +95,22 @@ namespace logs
|
||||
atomic_t<level> enabled;
|
||||
|
||||
// Initialize channel
|
||||
constexpr channel(const char* name) noexcept
|
||||
: name(name)
|
||||
consteval channel(const char* name) noexcept
|
||||
: message{}
|
||||
, name(name)
|
||||
, enabled(level::notice)
|
||||
{
|
||||
}
|
||||
|
||||
#define GEN_LOG_METHOD(_sev)\
|
||||
const message msg_##_sev{this, level::_sev};\
|
||||
template <typename... Args>\
|
||||
void _sev(const const_str& fmt, const Args&... args)\
|
||||
{\
|
||||
if (level::_sev <= enabled.observe()) [[unlikely]]\
|
||||
{\
|
||||
if constexpr (sizeof...(Args) > 0)\
|
||||
{\
|
||||
msg_##_sev.broadcast(fmt, fmt::type_info_v<Args...>, u64{fmt_unveil<Args>::get(args)}...);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
msg_##_sev.broadcast(fmt, nullptr);\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
// Special access to "always visible" channel which shouldn't be used
|
||||
const message& always() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define GEN_LOG_METHOD(_sev)\
|
||||
const message _sev{};\
|
||||
|
||||
GEN_LOG_METHOD(always)
|
||||
GEN_LOG_METHOD(fatal)
|
||||
GEN_LOG_METHOD(error)
|
||||
GEN_LOG_METHOD(todo)
|
||||
@ -112,6 +122,22 @@ namespace logs
|
||||
#undef GEN_LOG_METHOD
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
FORCE_INLINE SAFE_BUFFERS(void) message::operator()(const const_str& fmt, const Args&... args) const
|
||||
{
|
||||
if (*this < (*this)->enabled) [[unlikely]]
|
||||
{
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
{
|
||||
broadcast(fmt, fmt::type_info_v<Args...>, u64{fmt_unveil<Args>::get(args)}...);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcast(fmt, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct registerer
|
||||
{
|
||||
registerer(channel& _ch);
|
||||
|
@ -73,6 +73,10 @@ namespace std
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__INTELLISENSE__)
|
||||
#define consteval constexpr
|
||||
#endif
|
||||
|
||||
using schar = signed char;
|
||||
using uchar = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
|
Loading…
Reference in New Issue
Block a user