mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12: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
9 changed files with 95 additions and 69 deletions
|
@ -70,7 +70,7 @@ namespace vk
|
||||||
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties);
|
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties);
|
||||||
get_physical_device_features(allow_extensions);
|
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)
|
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
|
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: ";
|
std::string _msg = "RPCS3: ";
|
||||||
|
|
||||||
|
@ -197,9 +197,9 @@ struct fatal_error_listener final : logs::listener
|
||||||
_msg += ": ";
|
_msg += ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.ch && '\0' != *msg.ch->name)
|
if (msg->name && '\0' != *msg->name)
|
||||||
{
|
{
|
||||||
_msg += msg.ch->name;
|
_msg += msg->name;
|
||||||
_msg += ": ";
|
_msg += ": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,31 +446,19 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
{
|
{
|
||||||
// Write RPCS3 version
|
// Write RPCS3 version
|
||||||
logs::stored_message ver;
|
logs::stored_message ver{sys_log.always()};
|
||||||
ver.m.ch = nullptr;
|
|
||||||
ver.m.sev = logs::level::always;
|
|
||||||
ver.stamp = 0;
|
|
||||||
ver.text = fmt::format("RPCS3 v%s | %s", rpcs3::get_version().to_string(), rpcs3::get_branch());
|
ver.text = fmt::format("RPCS3 v%s | %s", rpcs3::get_version().to_string(), rpcs3::get_branch());
|
||||||
|
|
||||||
// Write System information
|
// Write System information
|
||||||
logs::stored_message sys;
|
logs::stored_message sys{sys_log.always()};
|
||||||
sys.m.ch = nullptr;
|
|
||||||
sys.m.sev = logs::level::always;
|
|
||||||
sys.stamp = 0;
|
|
||||||
sys.text = utils::get_system_info();
|
sys.text = utils::get_system_info();
|
||||||
|
|
||||||
// Write OS version
|
// Write OS version
|
||||||
logs::stored_message os;
|
logs::stored_message os{sys_log.always()};
|
||||||
os.m.ch = nullptr;
|
|
||||||
os.m.sev = logs::level::always;
|
|
||||||
os.stamp = 0;
|
|
||||||
os.text = utils::get_OS_version();
|
os.text = utils::get_OS_version();
|
||||||
|
|
||||||
// Write Qt version
|
// Write Qt version
|
||||||
logs::stored_message qt;
|
logs::stored_message qt{(strcmp(QT_VERSION_STR, qVersion()) != 0) ? sys_log.error : sys_log.notice};
|
||||||
qt.m.ch = nullptr;
|
|
||||||
qt.m.sev = (strcmp(QT_VERSION_STR, qVersion()) != 0) ? logs::level::error : logs::level::notice;
|
|
||||||
qt.stamp = 0;
|
|
||||||
qt.text = fmt::format("Qt version: Compiled against Qt %s | Run-time uses Qt %s", QT_VERSION_STR, qVersion());
|
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)});
|
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
|
// Log Firmware Version after Emu was initialized
|
||||||
const std::string firmware_version = utils::get_firmware_version();
|
const std::string firmware_version = utils::get_firmware_version();
|
||||||
const std::string firmware_string = firmware_version.empty() ? "Missing Firmware" : ("Firmware version: " + 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. */
|
/** 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
|
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
|
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 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_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_prefix = gui_save(logger, "prefix_on", false);
|
||||||
const gui_save l_stack = gui_save(logger, "stack", true);
|
const gui_save l_stack = gui_save(logger, "stack", true);
|
||||||
const gui_save l_stack_tty = gui_save(logger, "TTY_stack", false);
|
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
|
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
|
struct packet_t
|
||||||
{
|
{
|
||||||
|
@ -55,10 +55,10 @@ struct gui_listener : logs::listener
|
||||||
{
|
{
|
||||||
Q_UNUSED(stamp)
|
Q_UNUSED(stamp)
|
||||||
|
|
||||||
if (msg.sev <= enabled)
|
if (msg <= enabled)
|
||||||
{
|
{
|
||||||
packet_t p,* _new = &p;
|
packet_t p,* _new = &p;
|
||||||
_new->sev = msg.sev;
|
_new->sev = msg;
|
||||||
|
|
||||||
if (show_prefix && !prefix.empty())
|
if (show_prefix && !prefix.empty())
|
||||||
{
|
{
|
||||||
|
@ -67,12 +67,12 @@ struct gui_listener : logs::listener
|
||||||
_new->msg += "} ";
|
_new->msg += "} ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.ch && '\0' != *msg.ch->name)
|
if (msg->name && '\0' != *msg->name)
|
||||||
{
|
{
|
||||||
_new->msg += msg.ch->name;
|
_new->msg += msg->name;
|
||||||
_new->msg += msg.sev == logs::level::todo ? " TODO: " : ": ";
|
_new->msg += msg == logs::level::todo ? " TODO: " : ": ";
|
||||||
}
|
}
|
||||||
else if (msg.sev == logs::level::todo)
|
else if (msg == logs::level::todo)
|
||||||
{
|
{
|
||||||
_new->msg += "TODO: ";
|
_new->msg += "TODO: ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,14 @@ void fmt_class_string<logs::level>::format(std::string& out, u64 arg)
|
||||||
|
|
||||||
namespace logs
|
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
|
// Memory-mapped buffer size
|
||||||
constexpr u64 s_log_size = 32 * 1024 * 1024;
|
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);
|
text.reserve(50000);
|
||||||
|
|
||||||
// Used character: U+00B7 (Middle Dot)
|
// Used character: U+00B7 (Middle Dot)
|
||||||
switch (msg.sev)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case level::always: text = reinterpret_cast<const char*>(u8"·A "); break;
|
case level::always: text = reinterpret_cast<const char*>(u8"·A "); break;
|
||||||
case level::fatal: text = reinterpret_cast<const char*>(u8"·F "); 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);
|
const u64 frac = (stamp % 1'000'000);
|
||||||
fmt::append(text, "%u:%02u:%02u.%06u ", hours, mins, secs, frac);
|
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
|
// Workaround for first special messages to keep backward compatibility
|
||||||
text.clear();
|
text.clear();
|
||||||
|
@ -650,12 +658,12 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st
|
||||||
text += "} ";
|
text += "} ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.ch && '\0' != *msg.ch->name)
|
if (msg->name && '\0' != *msg->name)
|
||||||
{
|
{
|
||||||
text += msg.ch->name;
|
text += msg->name;
|
||||||
text += msg.sev == level::todo ? " TODO: " : ": ";
|
text += msg == level::todo ? " TODO: " : ": ";
|
||||||
}
|
}
|
||||||
else if (msg.sev == level::todo)
|
else if (msg == level::todo)
|
||||||
{
|
{
|
||||||
text += "TODO: ";
|
text += "TODO: ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,16 @@
|
||||||
|
|
||||||
namespace logs
|
namespace logs
|
||||||
{
|
{
|
||||||
enum class level : unsigned
|
enum class level : unsigned char
|
||||||
{
|
{
|
||||||
always, // Highest log severity (cannot be disabled)
|
always = 0, // Highest log severity (cannot be disabled)
|
||||||
fatal,
|
fatal = 1,
|
||||||
error,
|
error = 2,
|
||||||
todo,
|
todo = 3,
|
||||||
success,
|
success = 4,
|
||||||
warning,
|
warning = 5,
|
||||||
notice,
|
notice = 6,
|
||||||
trace, // Lowest severity (usually disabled)
|
trace = 7, // Lowest severity (usually disabled)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct channel;
|
struct channel;
|
||||||
|
@ -27,8 +27,27 @@ namespace logs
|
||||||
// Message information
|
// Message information
|
||||||
struct message
|
struct message
|
||||||
{
|
{
|
||||||
channel* ch;
|
// Default constructor
|
||||||
level sev;
|
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:
|
private:
|
||||||
// Send log message to global logger instance
|
// Send log message to global logger instance
|
||||||
|
@ -39,7 +58,7 @@ namespace logs
|
||||||
|
|
||||||
struct stored_message
|
struct stored_message
|
||||||
{
|
{
|
||||||
message m;
|
const message& m;
|
||||||
u64 stamp;
|
u64 stamp;
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
@ -67,7 +86,7 @@ namespace logs
|
||||||
void broadcast(const stored_message&) const;
|
void broadcast(const stored_message&) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct channel
|
struct alignas(16) channel : private message
|
||||||
{
|
{
|
||||||
// Channel prefix (added to every log message)
|
// Channel prefix (added to every log message)
|
||||||
const char* const name;
|
const char* const name;
|
||||||
|
@ -76,31 +95,22 @@ namespace logs
|
||||||
atomic_t<level> enabled;
|
atomic_t<level> enabled;
|
||||||
|
|
||||||
// Initialize channel
|
// Initialize channel
|
||||||
constexpr channel(const char* name) noexcept
|
consteval channel(const char* name) noexcept
|
||||||
: name(name)
|
: message{}
|
||||||
|
, name(name)
|
||||||
, enabled(level::notice)
|
, enabled(level::notice)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GEN_LOG_METHOD(_sev)\
|
// Special access to "always visible" channel which shouldn't be used
|
||||||
const message msg_##_sev{this, level::_sev};\
|
const message& always() const
|
||||||
template <typename... Args>\
|
{
|
||||||
void _sev(const const_str& fmt, const Args&... args)\
|
return *this;
|
||||||
{\
|
}
|
||||||
if (level::_sev <= enabled.observe()) [[unlikely]]\
|
|
||||||
{\
|
#define GEN_LOG_METHOD(_sev)\
|
||||||
if constexpr (sizeof...(Args) > 0)\
|
const message _sev{};\
|
||||||
{\
|
|
||||||
msg_##_sev.broadcast(fmt, fmt::type_info_v<Args...>, u64{fmt_unveil<Args>::get(args)}...);\
|
|
||||||
}\
|
|
||||||
else\
|
|
||||||
{\
|
|
||||||
msg_##_sev.broadcast(fmt, nullptr);\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
|
|
||||||
GEN_LOG_METHOD(always)
|
|
||||||
GEN_LOG_METHOD(fatal)
|
GEN_LOG_METHOD(fatal)
|
||||||
GEN_LOG_METHOD(error)
|
GEN_LOG_METHOD(error)
|
||||||
GEN_LOG_METHOD(todo)
|
GEN_LOG_METHOD(todo)
|
||||||
|
@ -112,6 +122,22 @@ namespace logs
|
||||||
#undef GEN_LOG_METHOD
|
#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
|
struct registerer
|
||||||
{
|
{
|
||||||
registerer(channel& _ch);
|
registerer(channel& _ch);
|
||||||
|
|
|
@ -73,6 +73,10 @@ namespace std
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__INTELLISENSE__)
|
||||||
|
#define consteval constexpr
|
||||||
|
#endif
|
||||||
|
|
||||||
using schar = signed char;
|
using schar = signed char;
|
||||||
using uchar = unsigned char;
|
using uchar = unsigned char;
|
||||||
using ushort = unsigned short;
|
using ushort = unsigned short;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue