diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/common/common_sizes.h | 43 | ||||
-rw-r--r-- | src/common/detached_tasks.cpp | 2 | ||||
-rw-r--r-- | src/common/fs/file.cpp | 14 | ||||
-rw-r--r-- | src/common/fs/file.h | 15 | ||||
-rw-r--r-- | src/common/fs/fs.cpp | 23 | ||||
-rw-r--r-- | src/common/fs/fs.h | 30 | ||||
-rw-r--r-- | src/common/hex_util.h | 3 | ||||
-rw-r--r-- | src/common/host_memory.cpp | 2 | ||||
-rw-r--r-- | src/common/literals.h | 31 | ||||
-rw-r--r-- | src/common/logging/backend.cpp | 160 | ||||
-rw-r--r-- | src/common/logging/backend.h | 43 | ||||
-rw-r--r-- | src/common/logging/filter.cpp | 132 | ||||
-rw-r--r-- | src/common/logging/filter.h | 12 | ||||
-rw-r--r-- | src/common/logging/log.h | 120 | ||||
-rw-r--r-- | src/common/logging/text_formatter.cpp | 2 | ||||
-rw-r--r-- | src/common/logging/types.h | 144 | ||||
-rw-r--r-- | src/common/settings.cpp | 5 | ||||
-rw-r--r-- | src/common/settings.h | 5 |
19 files changed, 422 insertions, 367 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 97fbdcbf9..a6fa9a85d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -110,7 +110,6 @@ add_library(common STATIC cityhash.cpp cityhash.h common_funcs.h - common_sizes.h common_types.h concepts.h div_ceil.h @@ -134,6 +133,7 @@ add_library(common STATIC host_memory.cpp host_memory.h intrusive_red_black_tree.h + literals.h logging/backend.cpp logging/backend.h logging/filter.cpp @@ -141,6 +141,7 @@ add_library(common STATIC logging/log.h logging/text_formatter.cpp logging/text_formatter.h + logging/types.h lz4_compression.cpp lz4_compression.h math_util.h diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h deleted file mode 100644 index 7e9fd968b..000000000 --- a/src/common/common_sizes.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <limits> - -#include "common/common_types.h" - -namespace Common { - -enum : u64 { - Size_1_KB = 0x400ULL, - Size_64_KB = 64ULL * Size_1_KB, - Size_128_KB = 128ULL * Size_1_KB, - Size_1_MB = 0x100000ULL, - Size_2_MB = 2ULL * Size_1_MB, - Size_4_MB = 4ULL * Size_1_MB, - Size_5_MB = 5ULL * Size_1_MB, - Size_14_MB = 14ULL * Size_1_MB, - Size_32_MB = 32ULL * Size_1_MB, - Size_33_MB = 33ULL * Size_1_MB, - Size_128_MB = 128ULL * Size_1_MB, - Size_448_MB = 448ULL * Size_1_MB, - Size_507_MB = 507ULL * Size_1_MB, - Size_562_MB = 562ULL * Size_1_MB, - Size_1554_MB = 1554ULL * Size_1_MB, - Size_2048_MB = 2048ULL * Size_1_MB, - Size_2193_MB = 2193ULL * Size_1_MB, - Size_3285_MB = 3285ULL * Size_1_MB, - Size_4916_MB = 4916ULL * Size_1_MB, - Size_1_GB = 0x40000000ULL, - Size_2_GB = 2ULL * Size_1_GB, - Size_4_GB = 4ULL * Size_1_GB, - Size_6_GB = 6ULL * Size_1_GB, - Size_8_GB = 8ULL * Size_1_GB, - Size_64_GB = 64ULL * Size_1_GB, - Size_512_GB = 512ULL * Size_1_GB, - Size_Invalid = std::numeric_limits<u64>::max(), -}; - -} // namespace Common diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp index f2b4939df..c1362631e 100644 --- a/src/common/detached_tasks.cpp +++ b/src/common/detached_tasks.cpp @@ -21,6 +21,8 @@ void DetachedTasks::WaitForAllTasks() { } DetachedTasks::~DetachedTasks() { + WaitForAllTasks(); + std::unique_lock lock{mutex}; ASSERT(count == 0); instance = nullptr; diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index 9f3de1cb0..077f34995 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp @@ -172,7 +172,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type) size_t WriteStringToFile(const std::filesystem::path& path, FileType type, std::string_view string) { - if (!IsFile(path)) { + if (Exists(path) && !IsFile(path)) { return 0; } @@ -183,11 +183,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type, size_t AppendStringToFile(const std::filesystem::path& path, FileType type, std::string_view string) { - if (!Exists(path)) { - return WriteStringToFile(path, type, string); - } - - if (!IsFile(path)) { + if (Exists(path) && !IsFile(path)) { return 0; } @@ -309,7 +305,11 @@ bool IOFile::Flush() const { errno = 0; - const auto flush_result = std::fflush(file) == 0; +#ifdef _WIN32 + const auto flush_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0; +#else + const auto flush_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0; +#endif if (!flush_result) { const auto ec = std::error_code{errno, std::generic_category()}; diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 50e270c5b..588fe619d 100644 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h @@ -49,7 +49,7 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op /** * Reads an entire file at path and returns a string of the contents read from the file. - * If the filesystem object at path is not a file, this function returns an empty string. + * If the filesystem object at path is not a regular file, this function returns an empty string. * * @param path Filesystem path * @param type File type @@ -71,8 +71,9 @@ template <typename Path> /** * Writes a string to a file at path and returns the number of characters successfully written. - * If an file already exists at path, its contents will be erased. - * If the filesystem object at path is not a file, this function returns 0. + * If a file already exists at path, its contents will be erased. + * If a file does not exist at path, it creates and opens a new empty file for writing. + * If the filesystem object at path exists and is not a regular file, this function returns 0. * * @param path Filesystem path * @param type File type @@ -95,8 +96,8 @@ template <typename Path> /** * Appends a string to a file at path and returns the number of characters successfully written. - * If a file does not exist at path, WriteStringToFile is called instead. - * If the filesystem object at path is not a file, this function returns 0. + * If a file does not exist at path, it creates and opens a new empty file for appending. + * If the filesystem object at path exists and is not a regular file, this function returns 0. * * @param path Filesystem path * @param type File type @@ -395,11 +396,11 @@ public: [[nodiscard]] size_t WriteString(std::span<const char> string) const; /** - * Flushes any unwritten buffered data into the file. + * Attempts to flush any unwritten buffered data into the file and flush the file into the disk. * * @returns True if the flush was successful, false otherwise. */ - [[nodiscard]] bool Flush() const; + bool Flush() const; /** * Resizes the file to a given size. diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp index d492480d9..9089cad67 100644 --- a/src/common/fs/fs.cpp +++ b/src/common/fs/fs.cpp @@ -135,8 +135,9 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File return nullptr; } - if (!IsFile(path)) { - LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file", + if (Exists(path) && !IsFile(path)) { + LOG_ERROR(Common_Filesystem, + "Filesystem object at path={} exists and is not a regular file", PathToUTF8String(path)); return nullptr; } @@ -321,7 +322,8 @@ bool RemoveDirContentsRecursively(const fs::path& path) { std::error_code ec; - for (const auto& entry : fs::recursive_directory_iterator(path, ec)) { + // TODO (Morph): Replace this with recursive_directory_iterator once it's fixed in MSVC. + for (const auto& entry : fs::directory_iterator(path, ec)) { if (ec) { LOG_ERROR(Common_Filesystem, "Failed to completely enumerate the directory at path={}, ec_message={}", @@ -337,6 +339,12 @@ bool RemoveDirContentsRecursively(const fs::path& path) { PathToUTF8String(entry.path()), ec.message()); break; } + + // TODO (Morph): Remove this when MSVC fixes recursive_directory_iterator. + // recursive_directory_iterator throws an exception despite passing in a std::error_code. + if (entry.status().type() == fs::file_type::directory) { + return RemoveDirContentsRecursively(entry.path()); + } } if (ec) { @@ -475,7 +483,8 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, std::error_code ec; - for (const auto& entry : fs::recursive_directory_iterator(path, ec)) { + // TODO (Morph): Replace this with recursive_directory_iterator once it's fixed in MSVC. + for (const auto& entry : fs::directory_iterator(path, ec)) { if (ec) { break; } @@ -495,6 +504,12 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path, break; } } + + // TODO (Morph): Remove this when MSVC fixes recursive_directory_iterator. + // recursive_directory_iterator throws an exception despite passing in a std::error_code. + if (entry.status().type() == fs::file_type::directory) { + IterateDirEntriesRecursively(entry.path(), callback, filter); + } } if (callback_error || ec) { diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h index f6f256349..183126de3 100644 --- a/src/common/fs/fs.h +++ b/src/common/fs/fs.h @@ -48,18 +48,18 @@ template <typename Path> * * Failures occur when: * - Input path is not valid - * - Filesystem object at path is not a file + * - Filesystem object at path is not a regular file * - Filesystem at path is read only * * @param path Filesystem path * * @returns True if file removal succeeds or file does not exist, false otherwise. */ -[[nodiscard]] bool RemoveFile(const std::filesystem::path& path); +bool RemoveFile(const std::filesystem::path& path); #ifdef _WIN32 template <typename Path> -[[nodiscard]] bool RemoveFile(const Path& path) { +bool RemoveFile(const Path& path) { if constexpr (IsChar<typename Path::value_type>) { return RemoveFile(ToU8String(path)); } else { @@ -74,7 +74,7 @@ template <typename Path> * Failures occur when: * - One or both input path(s) is not valid * - Filesystem object at old_path does not exist - * - Filesystem object at old_path is not a file + * - Filesystem object at old_path is not a regular file * - Filesystem object at new_path exists * - Filesystem at either path is read only * @@ -110,8 +110,8 @@ template <typename Path1, typename Path2> * * Failures occur when: * - Input path is not valid - * - Filesystem object at path is not a file - * - The file is not opened + * - Filesystem object at path exists and is not a regular file + * - The file is not open * * @param path Filesystem path * @param mode File access mode @@ -251,11 +251,11 @@ template <typename Path> * * @returns True if directory removal succeeds or directory does not exist, false otherwise. */ -[[nodiscard]] bool RemoveDir(const std::filesystem::path& path); +bool RemoveDir(const std::filesystem::path& path); #ifdef _WIN32 template <typename Path> -[[nodiscard]] bool RemoveDir(const Path& path) { +bool RemoveDir(const Path& path) { if constexpr (IsChar<typename Path::value_type>) { return RemoveDir(ToU8String(path)); } else { @@ -276,11 +276,11 @@ template <typename Path> * * @returns True if the directory and all of its contents are removed successfully, false otherwise. */ -[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path); +bool RemoveDirRecursively(const std::filesystem::path& path); #ifdef _WIN32 template <typename Path> -[[nodiscard]] bool RemoveDirRecursively(const Path& path) { +bool RemoveDirRecursively(const Path& path) { if constexpr (IsChar<typename Path::value_type>) { return RemoveDirRecursively(ToU8String(path)); } else { @@ -301,11 +301,11 @@ template <typename Path> * * @returns True if all of the directory's contents are removed successfully, false otherwise. */ -[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path); +bool RemoveDirContentsRecursively(const std::filesystem::path& path); #ifdef _WIN32 template <typename Path> -[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) { +bool RemoveDirContentsRecursively(const Path& path) { if constexpr (IsChar<typename Path::value_type>) { return RemoveDirContentsRecursively(ToU8String(path)); } else { @@ -435,11 +435,13 @@ template <typename Path> #endif /** - * Returns whether a filesystem object at path is a file. + * Returns whether a filesystem object at path is a regular file. + * A regular file is a file that stores text or binary data. + * It is not a directory, symlink, FIFO, socket, block device, or character device. * * @param path Filesystem path * - * @returns True if a filesystem object at path is a file, false otherwise. + * @returns True if a filesystem object at path is a regular file, false otherwise. */ [[nodiscard]] bool IsFile(const std::filesystem::path& path); diff --git a/src/common/hex_util.h b/src/common/hex_util.h index a8d414fb8..f5f9e4507 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h @@ -53,8 +53,9 @@ template <typename ContiguousContainer> std::string out; out.reserve(std::size(data) * pad_width); + const auto format_str = fmt::runtime(upper ? "{:02X}" : "{:02x}"); for (const u8 c : data) { - out += fmt::format(upper ? "{:02X}" : "{:02x}", c); + out += fmt::format(format_str, c); } return out; diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 8bd70abc7..2a5a7596c 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -34,7 +34,7 @@ constexpr size_t HugePageSize = 0x200000; // Manually imported for MinGW compatibility #ifndef MEM_RESERVE_PLACEHOLDER -#define MEM_RESERVE_PLACEHOLDER 0x0004000 +#define MEM_RESERVE_PLACEHOLDER 0x00040000 #endif #ifndef MEM_REPLACE_PLACEHOLDER #define MEM_REPLACE_PLACEHOLDER 0x00004000 diff --git a/src/common/literals.h b/src/common/literals.h new file mode 100644 index 000000000..d55fed40b --- /dev/null +++ b/src/common/literals.h @@ -0,0 +1,31 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace Common::Literals { + +constexpr u64 operator""_KiB(unsigned long long int x) { + return 1024ULL * x; +} + +constexpr u64 operator""_MiB(unsigned long long int x) { + return 1024_KiB * x; +} + +constexpr u64 operator""_GiB(unsigned long long int x) { + return 1024_MiB * x; +} + +constexpr u64 operator""_TiB(unsigned long long int x) { + return 1024_GiB * x; +} + +constexpr u64 operator""_PiB(unsigned long long int x) { + return 1024_TiB * x; +} + +} // namespace Common::Literals diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 6aa8ac960..b6fa4affb 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -17,7 +17,10 @@ #endif #include "common/assert.h" +#include "common/fs/file.h" #include "common/fs/fs.h" +#include "common/literals.h" + #include "common/logging/backend.h" #include "common/logging/log.h" #include "common/logging/text_formatter.h" @@ -97,8 +100,8 @@ private: write_logs(entry); } - // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case - // where a system is repeatedly spamming logs even on close. + // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a + // case where a system is repeatedly spamming logs even on close. const int MAX_LOGS_TO_WRITE = filter.IsDebug() ? INT_MAX : 100; int logs_written = 0; while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) { @@ -140,10 +143,14 @@ private: std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; }; +ConsoleBackend::~ConsoleBackend() = default; + void ConsoleBackend::Write(const Entry& entry) { PrintMessage(entry); } +ColorConsoleBackend::~ColorConsoleBackend() = default; + void ColorConsoleBackend::Write(const Entry& entry) { PrintColoredMessage(entry); } @@ -154,19 +161,23 @@ FileBackend::FileBackend(const std::filesystem::path& filename) { // Existence checks are done within the functions themselves. // We don't particularly care if these succeed or not. - void(FS::RemoveFile(old_filename)); + FS::RemoveFile(old_filename); void(FS::RenameFile(filename, old_filename)); - file = FS::IOFile(filename, FS::FileAccessMode::Write, FS::FileType::TextFile); + file = + std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile); } +FileBackend::~FileBackend() = default; + void FileBackend::Write(const Entry& entry) { + using namespace Common::Literals; // prevent logs from going over the maximum size (in case its spamming and the user doesn't // know) - constexpr std::size_t MAX_BYTES_WRITTEN = 100 * 1024 * 1024; - constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1024 * 1024 * 1024; + constexpr std::size_t MAX_BYTES_WRITTEN = 100_MiB; + constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1_GiB; - if (!file.IsOpen()) { + if (!file->IsOpen()) { return; } @@ -176,147 +187,20 @@ void FileBackend::Write(const Entry& entry) { return; } - bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); + bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); if (entry.log_level >= Level::Error) { - void(file.Flush()); + file->Flush(); } } +DebuggerBackend::~DebuggerBackend() = default; + void DebuggerBackend::Write(const Entry& entry) { #ifdef _WIN32 ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); #endif } -/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. -#define ALL_LOG_CLASSES() \ - CLS(Log) \ - CLS(Common) \ - SUB(Common, Filesystem) \ - SUB(Common, Memory) \ - CLS(Core) \ - SUB(Core, ARM) \ - SUB(Core, Timing) \ - CLS(Config) \ - CLS(Debug) \ - SUB(Debug, Emulated) \ - SUB(Debug, GPU) \ - SUB(Debug, Breakpoint) \ - SUB(Debug, GDBStub) \ - CLS(Kernel) \ - SUB(Kernel, SVC) \ - CLS(Service) \ - SUB(Service, ACC) \ - SUB(Service, Audio) \ - SUB(Service, AM) \ - SUB(Service, AOC) \ - SUB(Service, APM) \ - SUB(Service, ARP) \ - SUB(Service, BCAT) \ - SUB(Service, BPC) \ - SUB(Service, BGTC) \ - SUB(Service, BTDRV) \ - SUB(Service, BTM) \ - SUB(Service, Capture) \ - SUB(Service, ERPT) \ - SUB(Service, ETicket) \ - SUB(Service, EUPLD) \ - SUB(Service, Fatal) \ - SUB(Service, FGM) \ - SUB(Service, Friend) \ - SUB(Service, FS) \ - SUB(Service, GRC) \ - SUB(Service, HID) \ - SUB(Service, IRS) \ - SUB(Service, LBL) \ - SUB(Service, LDN) \ - SUB(Service, LDR) \ - SUB(Service, LM) \ - SUB(Service, Migration) \ - SUB(Service, Mii) \ - SUB(Service, MM) \ - SUB(Service, NCM) \ - SUB(Service, NFC) \ - SUB(Service, NFP) \ - SUB(Service, NIFM) \ - SUB(Service, NIM) \ - SUB(Service, NPNS) \ - SUB(Service, NS) \ - SUB(Service, NVDRV) \ - SUB(Service, OLSC) \ - SUB(Service, PCIE) \ - SUB(Service, PCTL) \ - SUB(Service, PCV) \ - SUB(Service, PM) \ - SUB(Service, PREPO) \ - SUB(Service, PSC) \ - SUB(Service, PSM) \ - SUB(Service, SET) \ - SUB(Service, SM) \ - SUB(Service, SPL) \ - SUB(Service, SSL) \ - SUB(Service, TCAP) \ - SUB(Service, Time) \ - SUB(Service, USB) \ - SUB(Service, VI) \ - SUB(Service, WLAN) \ - CLS(HW) \ - SUB(HW, Memory) \ - SUB(HW, LCD) \ - SUB(HW, GPU) \ - SUB(HW, AES) \ - CLS(IPC) \ - CLS(Frontend) \ - CLS(Render) \ - SUB(Render, Software) \ - SUB(Render, OpenGL) \ - SUB(Render, Vulkan) \ - CLS(Audio) \ - SUB(Audio, DSP) \ - SUB(Audio, Sink) \ - CLS(Input) \ - CLS(Network) \ - CLS(Loader) \ - CLS(CheatEngine) \ - CLS(Crypto) \ - CLS(WebService) - -// GetClassName is a macro defined by Windows.h, grrr... -const char* GetLogClassName(Class log_class) { - switch (log_class) { -#define CLS(x) \ - case Class::x: \ - return #x; -#define SUB(x, y) \ - case Class::x##_##y: \ - return #x "." #y; - ALL_LOG_CLASSES() -#undef CLS -#undef SUB - case Class::Count: - break; - } - return "Invalid"; -} - -const char* GetLevelName(Level log_level) { -#define LVL(x) \ - case Level::x: \ - return #x - switch (log_level) { - LVL(Trace); - LVL(Debug); - LVL(Info); - LVL(Warning); - LVL(Error); - LVL(Critical); - case Level::Count: - break; - } -#undef LVL - return "Invalid"; -} - void SetGlobalFilter(const Filter& filter) { Impl::Instance().SetGlobalFilter(filter); } diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index eb629a33f..4b9a910c1 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -1,43 +1,32 @@ // Copyright 2014 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. + #pragma once -#include <chrono> #include <filesystem> #include <memory> #include <string> #include <string_view> -#include "common/fs/file.h" #include "common/logging/filter.h" #include "common/logging/log.h" +namespace Common::FS { +class IOFile; +} + namespace Common::Log { class Filter; /** - * A log entry. Log entries are store in a structured format to permit more varied output - * formatting on different frontends, as well as facilitating filtering and aggregation. - */ -struct Entry { - std::chrono::microseconds timestamp; - Class log_class{}; - Level log_level{}; - const char* filename = nullptr; - unsigned int line_num = 0; - std::string function; - std::string message; - bool final_entry = false; -}; - -/** * Interface for logging backends. As loggers can be created and removed at runtime, this can be * used by a frontend for adding a custom logging backend as needed */ class Backend { public: virtual ~Backend() = default; + virtual void SetFilter(const Filter& new_filter) { filter = new_filter; } @@ -53,6 +42,8 @@ private: */ class ConsoleBackend : public Backend { public: + ~ConsoleBackend() override; + static const char* Name() { return "console"; } @@ -67,6 +58,8 @@ public: */ class ColorConsoleBackend : public Backend { public: + ~ColorConsoleBackend() override; + static const char* Name() { return "color_console"; } @@ -83,6 +76,7 @@ public: class FileBackend : public Backend { public: explicit FileBackend(const std::filesystem::path& filename); + ~FileBackend() override; static const char* Name() { return "file"; @@ -95,7 +89,7 @@ public: void Write(const Entry& entry) override; private: - FS::IOFile file; + std::unique_ptr<FS::IOFile> file; std::size_t bytes_written = 0; }; @@ -104,6 +98,8 @@ private: */ class DebuggerBackend : public Backend { public: + ~DebuggerBackend() override; + static const char* Name() { return "debugger"; } @@ -120,17 +116,6 @@ void RemoveBackend(std::string_view backend_name); Backend* GetBackend(std::string_view backend_name); /** - * Returns the name of the passed log class as a C-string. Subclasses are separated by periods - * instead of underscores as in the enumeration. - */ -const char* GetLogClassName(Class log_class); - -/** - * Returns the name of the passed log level as a C-string. - */ -const char* GetLevelName(Level log_level); - -/** * The global filter will prevent any messages from even being processed if they are filtered. Each * backend can have a filter, but if the level is lower than the global filter, the backend will * never get the message diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 20a2dd106..4f2cc29e1 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include <algorithm> -#include "common/logging/backend.h" #include "common/logging/filter.h" #include "common/string_util.h" @@ -22,7 +21,7 @@ Level GetLevelByName(const It begin, const It end) { template <typename It> Class GetClassByName(const It begin, const It end) { - for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) { + for (u8 i = 0; i < static_cast<u8>(Class::Count); ++i) { const char* level_name = GetLogClassName(static_cast<Class>(i)); if (Common::ComparePartialString(begin, end, level_name)) { return static_cast<Class>(i); @@ -62,6 +61,135 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { } } // Anonymous namespace +/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. +#define ALL_LOG_CLASSES() \ + CLS(Log) \ + CLS(Common) \ + SUB(Common, Filesystem) \ + SUB(Common, Memory) \ + CLS(Core) \ + SUB(Core, ARM) \ + SUB(Core, Timing) \ + CLS(Config) \ + CLS(Debug) \ + SUB(Debug, Emulated) \ + SUB(Debug, GPU) \ + SUB(Debug, Breakpoint) \ + SUB(Debug, GDBStub) \ + CLS(Kernel) \ + SUB(Kernel, SVC) \ + CLS(Service) \ + SUB(Service, ACC) \ + SUB(Service, Audio) \ + SUB(Service, AM) \ + SUB(Service, AOC) \ + SUB(Service, APM) \ + SUB(Service, ARP) \ + SUB(Service, BCAT) \ + SUB(Service, BPC) \ + SUB(Service, BGTC) \ + SUB(Service, BTDRV) \ + SUB(Service, BTM) \ + SUB(Service, Capture) \ + SUB(Service, ERPT) \ + SUB(Service, ETicket) \ + SUB(Service, EUPLD) \ + SUB(Service, Fatal) \ + SUB(Service, FGM) \ + SUB(Service, Friend) \ + SUB(Service, FS) \ + SUB(Service, GRC) \ + SUB(Service, HID) \ + SUB(Service, IRS) \ + SUB(Service, LBL) \ + SUB(Service, LDN) \ + SUB(Service, LDR) \ + SUB(Service, LM) \ + SUB(Service, Migration) \ + SUB(Service, Mii) \ + SUB(Service, MM) \ + SUB(Service, NCM) \ + SUB(Service, NFC) \ + SUB(Service, NFP) \ + SUB(Service, NIFM) \ + SUB(Service, NIM) \ + SUB(Service, NPNS) \ + SUB(Service, NS) \ + SUB(Service, NVDRV) \ + SUB(Service, OLSC) \ + SUB(Service, PCIE) \ + SUB(Service, PCTL) \ + SUB(Service, PCV) \ + SUB(Service, PM) \ + SUB(Service, PREPO) \ + SUB(Service, PSC) \ + SUB(Service, PSM) \ + SUB(Service, SET) \ + SUB(Service, SM) \ + SUB(Service, SPL) \ + SUB(Service, SSL) \ + SUB(Service, TCAP) \ + SUB(Service, Time) \ + SUB(Service, USB) \ + SUB(Service, VI) \ + SUB(Service, WLAN) \ + CLS(HW) \ + SUB(HW, Memory) \ + SUB(HW, LCD) \ + SUB(HW, GPU) \ + SUB(HW, AES) \ + CLS(IPC) \ + CLS(Frontend) \ + CLS(Render) \ + SUB(Render, Software) \ + SUB(Render, OpenGL) \ + SUB(Render, Vulkan) \ + CLS(Audio) \ + SUB(Audio, DSP) \ + SUB(Audio, Sink) \ + CLS(Input) \ + CLS(Network) \ + CLS(Loader) \ + CLS(CheatEngine) \ + CLS(Crypto) \ + CLS(WebService) + +// GetClassName is a macro defined by Windows.h, grrr... +const char* GetLogClassName(Class log_class) { + switch (log_class) { +#define CLS(x) \ + case Class::x: \ + return #x; +#define SUB(x, y) \ + case Class::x##_##y: \ + return #x "." #y; + ALL_LOG_CLASSES() +#undef CLS +#undef SUB + case Class::Count: + break; + } + return "Invalid"; +} + +const char* GetLevelName(Level log_level) { +#define LVL(x) \ + case Level::x: \ + return #x + switch (log_level) { + LVL(Trace); + LVL(Debug); + LVL(Info); + LVL(Warning); + LVL(Error); + LVL(Critical); + case Level::Count: + break; + } +#undef LVL + return "Invalid"; +} + Filter::Filter(Level default_level) { ResetAll(default_level); } diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h index f5673a9f6..1a3074e04 100644 --- a/src/common/logging/filter.h +++ b/src/common/logging/filter.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <chrono> #include <cstddef> #include <string_view> #include "common/logging/log.h" @@ -12,6 +13,17 @@ namespace Common::Log { /** + * Returns the name of the passed log class as a C-string. Subclasses are separated by periods + * instead of underscores as in the enumeration. + */ +const char* GetLogClassName(Class log_class); + +/** + * Returns the name of the passed log level as a C-string. + */ +const char* GetLevelName(Level log_level); + +/** * Implements a log message filter which allows different log classes to have different minimum * severity levels. The filter can be changed at runtime and can be parsed from a string to allow * editing via the interface or loading from a configuration file. diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 1f0f8db52..8d43eddc7 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -5,7 +5,7 @@ #pragma once #include <fmt/format.h> -#include "common/common_types.h" +#include "common/logging/types.h" namespace Common::Log { @@ -18,124 +18,6 @@ constexpr const char* TrimSourcePath(std::string_view source) { return source.data() + idx; } -/// Specifies the severity or level of detail of the log message. -enum class Level : u8 { - Trace, ///< Extremely detailed and repetitive debugging information that is likely to - ///< pollute logs. - Debug, ///< Less detailed debugging information. - Info, ///< Status information from important points during execution. - Warning, ///< Minor or potential problems found during execution of a task. - Error, ///< Major problems found during execution of a task that prevent it from being - ///< completed. - Critical, ///< Major problems during execution that threaten the stability of the entire - ///< application. - - Count ///< Total number of logging levels -}; - -typedef u8 ClassType; - -/** - * Specifies the sub-system that generated the log message. - * - * @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in - * backend.cpp. - */ -enum class Class : ClassType { - Log, ///< Messages about the log system itself - Common, ///< Library routines - Common_Filesystem, ///< Filesystem interface library - Common_Memory, ///< Memory mapping and management functions - Core, ///< LLE emulation core - Core_ARM, ///< ARM CPU core - Core_Timing, ///< CoreTiming functions - Config, ///< Emulator configuration (including commandline) - Debug, ///< Debugging tools - Debug_Emulated, ///< Debug messages from the emulated programs - Debug_GPU, ///< GPU debugging tools - Debug_Breakpoint, ///< Logging breakpoints and watchpoints - Debug_GDBStub, ///< GDB Stub - Kernel, ///< The HLE implementation of the CTR kernel - Kernel_SVC, ///< Kernel system calls - Service, ///< HLE implementation of system services. Each major service - ///< should have its own subclass. - Service_ACC, ///< The ACC (Accounts) service - Service_AM, ///< The AM (Applet manager) service - Service_AOC, ///< The AOC (AddOn Content) service - Service_APM, ///< The APM (Performance) service - Service_ARP, ///< The ARP service - Service_Audio, ///< The Audio (Audio control) service - Service_BCAT, ///< The BCAT service - Service_BGTC, ///< The BGTC (Background Task Controller) service - Service_BPC, ///< The BPC service - Service_BTDRV, ///< The Bluetooth driver service - Service_BTM, ///< The BTM service - Service_Capture, ///< The capture service - Service_ERPT, ///< The error reporting service - Service_ETicket, ///< The ETicket service - Service_EUPLD, ///< The error upload service - Service_Fatal, ///< The Fatal service - Service_FGM, ///< The FGM service - Service_Friend, ///< The friend service - Service_FS, ///< The FS (Filesystem) service - Service_GRC, ///< The game recording service - Service_HID, ///< The HID (Human interface device) service - Service_IRS, ///< The IRS service - Service_LBL, ///< The LBL (LCD backlight) service - Service_LDN, ///< The LDN (Local domain network) service - Service_LDR, ///< The loader service - Service_LM, ///< The LM (Logger) service - Service_Migration, ///< The migration service - Service_Mii, ///< The Mii service - Service_MM, ///< The MM (Multimedia) service - Service_NCM, ///< The NCM service - Service_NFC, ///< The NFC (Near-field communication) service - Service_NFP, ///< The NFP service - Service_NIFM, ///< The NIFM (Network interface) service - Service_NIM, ///< The NIM service - Service_NPNS, ///< The NPNS service - Service_NS, ///< The NS services - Service_NVDRV, ///< The NVDRV (Nvidia driver) service - Service_OLSC, ///< The OLSC service - Service_PCIE, ///< The PCIe service - Service_PCTL, ///< The PCTL (Parental control) service - Service_PCV, ///< The PCV service - Service_PM, ///< The PM service - Service_PREPO, ///< The PREPO (Play report) service - Service_PSC, ///< The PSC service - Service_PSM, ///< The PSM service - Service_SET, ///< The SET (Settings) service - Service_SM, ///< The SM (Service manager) service - Service_SPL, ///< The SPL service - Service_SSL, ///< The SSL service - Service_TCAP, ///< The TCAP service. - Service_Time, ///< The time service - Service_USB, ///< The USB (Universal Serial Bus) service - Service_VI, ///< The VI (Video interface) service - Service_WLAN, ///< The WLAN (Wireless local area network) service - HW, ///< Low-level hardware emulation - HW_Memory, ///< Memory-map and address translation - HW_LCD, ///< LCD register emulation - HW_GPU, ///< GPU control emulation - HW_AES, ///< AES engine emulation - IPC, ///< IPC interface - Frontend, ///< Emulator UI - Render, ///< Emulator video output and hardware acceleration - Render_Software, ///< Software renderer backend - Render_OpenGL, ///< OpenGL backend - Render_Vulkan, ///< Vulkan backend - Audio, ///< Audio emulation - Audio_DSP, ///< The HLE implementation of the DSP - Audio_Sink, ///< Emulator audio output backend - Loader, ///< ROM loader - CheatEngine, ///< Memory manipulation and engine VM functions - Crypto, ///< Cryptographic engine/functions - Input, ///< Input emulation - Network, ///< Network emulation - WebService, ///< Interface to yuzu Web Services - Count ///< Total number of logging classes -}; - /// Logs a message to the global logger, using fmt void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, const char* format, diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp index 80ee2cca1..cfc0d5846 100644 --- a/src/common/logging/text_formatter.cpp +++ b/src/common/logging/text_formatter.cpp @@ -11,7 +11,7 @@ #include "common/assert.h" #include "common/common_funcs.h" -#include "common/logging/backend.h" +#include "common/logging/filter.h" #include "common/logging/log.h" #include "common/logging/text_formatter.h" #include "common/string_util.h" diff --git a/src/common/logging/types.h b/src/common/logging/types.h new file mode 100644 index 000000000..88b0e9c01 --- /dev/null +++ b/src/common/logging/types.h @@ -0,0 +1,144 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <chrono> + +#include "common/common_types.h" + +namespace Common::Log { + +/// Specifies the severity or level of detail of the log message. +enum class Level : u8 { + Trace, ///< Extremely detailed and repetitive debugging information that is likely to + ///< pollute logs. + Debug, ///< Less detailed debugging information. + Info, ///< Status information from important points during execution. + Warning, ///< Minor or potential problems found during execution of a task. + Error, ///< Major problems found during execution of a task that prevent it from being + ///< completed. + Critical, ///< Major problems during execution that threaten the stability of the entire + ///< application. + + Count ///< Total number of logging levels +}; + +/** + * Specifies the sub-system that generated the log message. + * + * @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in + * filter.cpp. + */ +enum class Class : u8 { + Log, ///< Messages about the log system itself + Common, ///< Library routines + Common_Filesystem, ///< Filesystem interface library + Common_Memory, ///< Memory mapping and management functions + Core, ///< LLE emulation core + Core_ARM, ///< ARM CPU core + Core_Timing, ///< CoreTiming functions + Config, ///< Emulator configuration (including commandline) + Debug, ///< Debugging tools + Debug_Emulated, ///< Debug messages from the emulated programs + Debug_GPU, ///< GPU debugging tools + Debug_Breakpoint, ///< Logging breakpoints and watchpoints + Debug_GDBStub, ///< GDB Stub + Kernel, ///< The HLE implementation of the CTR kernel + Kernel_SVC, ///< Kernel system calls + Service, ///< HLE implementation of system services. Each major service + ///< should have its own subclass. + Service_ACC, ///< The ACC (Accounts) service + Service_AM, ///< The AM (Applet manager) service + Service_AOC, ///< The AOC (AddOn Content) service + Service_APM, ///< The APM (Performance) service + Service_ARP, ///< The ARP service + Service_Audio, ///< The Audio (Audio control) service + Service_BCAT, ///< The BCAT service + Service_BGTC, ///< The BGTC (Background Task Controller) service + Service_BPC, ///< The BPC service + Service_BTDRV, ///< The Bluetooth driver service + Service_BTM, ///< The BTM service + Service_Capture, ///< The capture service + Service_ERPT, ///< The error reporting service + Service_ETicket, ///< The ETicket service + Service_EUPLD, ///< The error upload service + Service_Fatal, ///< The Fatal service + Service_FGM, ///< The FGM service + Service_Friend, ///< The friend service + Service_FS, ///< The FS (Filesystem) service + Service_GRC, ///< The game recording service + Service_HID, ///< The HID (Human interface device) service + Service_IRS, ///< The IRS service + Service_LBL, ///< The LBL (LCD backlight) service + Service_LDN, ///< The LDN (Local domain network) service + Service_LDR, ///< The loader service + Service_LM, ///< The LM (Logger) service + Service_Migration, ///< The migration service + Service_Mii, ///< The Mii service + Service_MM, ///< The MM (Multimedia) service + Service_NCM, ///< The NCM service + Service_NFC, ///< The NFC (Near-field communication) service + Service_NFP, ///< The NFP service + Service_NIFM, ///< The NIFM (Network interface) service + Service_NIM, ///< The NIM service + Service_NPNS, ///< The NPNS service + Service_NS, ///< The NS services + Service_NVDRV, ///< The NVDRV (Nvidia driver) service + Service_OLSC, ///< The OLSC service + Service_PCIE, ///< The PCIe service + Service_PCTL, ///< The PCTL (Parental control) service + Service_PCV, ///< The PCV service + Service_PM, ///< The PM service + Service_PREPO, ///< The PREPO (Play report) service + Service_PSC, ///< The PSC service + Service_PSM, ///< The PSM service + Service_SET, ///< The SET (Settings) service + Service_SM, ///< The SM (Service manager) service + Service_SPL, ///< The SPL service + Service_SSL, ///< The SSL service + Service_TCAP, ///< The TCAP service. + Service_Time, ///< The time service + Service_USB, ///< The USB (Universal Serial Bus) service + Service_VI, ///< The VI (Video interface) service + Service_WLAN, ///< The WLAN (Wireless local area network) service + HW, ///< Low-level hardware emulation + HW_Memory, ///< Memory-map and address translation + HW_LCD, ///< LCD register emulation + HW_GPU, ///< GPU control emulation + HW_AES, ///< AES engine emulation + IPC, ///< IPC interface + Frontend, ///< Emulator UI + Render, ///< Emulator video output and hardware acceleration + Render_Software, ///< Software renderer backend + Render_OpenGL, ///< OpenGL backend + Render_Vulkan, ///< Vulkan backend + Audio, ///< Audio emulation + Audio_DSP, ///< The HLE implementation of the DSP + Audio_Sink, ///< Emulator audio output backend + Loader, ///< ROM loader + CheatEngine, ///< Memory manipulation and engine VM functions + Crypto, ///< Cryptographic engine/functions + Input, ///< Input emulation + Network, ///< Network emulation + WebService, ///< Interface to yuzu Web Services + Count ///< Total number of logging classes +}; + +/** + * A log entry. Log entries are store in a structured format to permit more varied output + * formatting on different frontends, as well as facilitating filtering and aggregation. + */ +struct Entry { + std::chrono::microseconds timestamp; + Class log_class{}; + Level log_level{}; + const char* filename = nullptr; + unsigned int line_num = 0; + std::string function; + std::string message; + bool final_entry = false; +}; + +} // namespace Common::Log diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 360e878d6..e1bb4b7ff 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -55,9 +55,11 @@ void LogSettings() { log_setting("Renderer_UseAsynchronousGpuEmulation", values.use_asynchronous_gpu_emulation.GetValue()); log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); + log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); + log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue()); log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); log_setting("Audio_OutputEngine", values.sink_id); log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); @@ -121,6 +123,7 @@ void RestoreGlobalState(bool is_powered_on) { values.cpu_accuracy.SetGlobal(true); values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); + values.cpuopt_unsafe_ignore_standard_fpcr.SetGlobal(true); values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); values.cpuopt_unsafe_fastmem_check.SetGlobal(true); @@ -135,10 +138,12 @@ void RestoreGlobalState(bool is_powered_on) { values.gpu_accuracy.SetGlobal(true); values.use_asynchronous_gpu_emulation.SetGlobal(true); values.use_nvdec_emulation.SetGlobal(true); + values.accelerate_astc.SetGlobal(true); values.use_vsync.SetGlobal(true); values.use_assembly_shaders.SetGlobal(true); values.use_asynchronous_shaders.SetGlobal(true); values.use_fast_gpu_time.SetGlobal(true); + values.use_caches_gc.SetGlobal(true); values.bg_red.SetGlobal(true); values.bg_green.SetGlobal(true); values.bg_blue.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 1af8c5ac2..82ec18e27 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -129,6 +129,7 @@ struct Values { Setting<bool> cpuopt_unsafe_unfuse_fma; Setting<bool> cpuopt_unsafe_reduce_fp_error; + Setting<bool> cpuopt_unsafe_ignore_standard_fpcr; Setting<bool> cpuopt_unsafe_inaccurate_nan; Setting<bool> cpuopt_unsafe_fastmem_check; @@ -147,10 +148,13 @@ struct Values { Setting<GPUAccuracy> gpu_accuracy; Setting<bool> use_asynchronous_gpu_emulation; Setting<bool> use_nvdec_emulation; + Setting<bool> accelerate_astc; Setting<bool> use_vsync; + Setting<bool> disable_fps_limit; Setting<bool> use_assembly_shaders; Setting<bool> use_asynchronous_shaders; Setting<bool> use_fast_gpu_time; + Setting<bool> use_caches_gc; Setting<float> bg_red; Setting<float> bg_green; @@ -218,6 +222,7 @@ struct Values { std::string program_args; bool dump_exefs; bool dump_nso; + bool enable_fs_access_log; bool reporting_services; bool quest_flag; bool disable_macro_jit; |