Compare commits
28 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb2624ed65 | ||
|
|
3de38c9a70 | ||
|
|
3843995ceb | ||
|
|
de71a4d70d | ||
|
|
4654fb96b0 | ||
|
|
4d535799eb | ||
|
|
84b4ac5729 | ||
|
|
bed0c3c92a | ||
|
|
7eb4542c1d | ||
|
|
f65f8b9097 | ||
|
|
6fef91ce4c | ||
|
|
a428a843cb | ||
|
|
c4a1d3cbf4 | ||
|
|
bde6b899a1 | ||
|
|
455e28790a | ||
|
|
519978ce70 | ||
|
|
0821d95399 | ||
|
|
155b99ee55 | ||
|
|
ef2066b272 | ||
|
|
d82fc52cea | ||
|
|
151ab86204 | ||
|
|
40674b8e22 | ||
|
|
4fd655cb46 | ||
|
|
beb7305b73 | ||
|
|
14e93f133a | ||
|
|
af6290ed12 | ||
|
|
1770503185 | ||
|
|
001675dced |
5
externals/CMakeLists.txt
vendored
5
externals/CMakeLists.txt
vendored
@@ -7,7 +7,9 @@ include(DownloadExternals)
|
||||
# xbyak
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
add_library(xbyak INTERFACE)
|
||||
target_include_directories(xbyak SYSTEM INTERFACE ./xbyak/xbyak)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/xbyak/xbyak DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
target_include_directories(xbyak SYSTEM INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
|
||||
target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES)
|
||||
endif()
|
||||
|
||||
@@ -19,6 +21,7 @@ target_include_directories(catch-single-include INTERFACE catch/single_include)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
set(DYNARMIC_TESTS OFF)
|
||||
set(DYNARMIC_NO_BUNDLED_FMT ON)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(dynarmic)
|
||||
endif()
|
||||
|
||||
|
||||
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 7946868af4...517e35f845
@@ -2,13 +2,10 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -16,28 +13,173 @@
|
||||
#include <windows.h> // For OutputDebugStringW
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/fs_paths.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/literals.h"
|
||||
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/text_formatter.h"
|
||||
#include "common/settings.h"
|
||||
#ifdef _WIN32
|
||||
#include "common/string_util.h"
|
||||
#endif
|
||||
#include "common/threadsafe_queue.h"
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Interface for logging backends.
|
||||
*/
|
||||
class Backend {
|
||||
public:
|
||||
virtual ~Backend() = default;
|
||||
|
||||
virtual void Write(const Entry& entry) = 0;
|
||||
|
||||
virtual void EnableForStacktrace() = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr and with color
|
||||
*/
|
||||
class ColorConsoleBackend final : public Backend {
|
||||
public:
|
||||
explicit ColorConsoleBackend() = default;
|
||||
|
||||
~ColorConsoleBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
if (enabled.load(std::memory_order_relaxed)) {
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() override {
|
||||
// stderr shouldn't be buffered
|
||||
}
|
||||
|
||||
void EnableForStacktrace() override {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
void SetEnabled(bool enabled_) {
|
||||
enabled = enabled_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_bool enabled{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to a file passed into the constructor
|
||||
*/
|
||||
class FileBackend final : public Backend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename) {
|
||||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
static_cast<void>(FS::RemoveFile(old_filename));
|
||||
static_cast<void>(FS::RenameFile(filename, old_filename));
|
||||
|
||||
file = std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write,
|
||||
FS::FileType::TextFile);
|
||||
}
|
||||
|
||||
~FileBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB;
|
||||
const bool write_limit_exceeded = bytes_written > write_limit;
|
||||
if (entry.log_level >= Level::Error || write_limit_exceeded) {
|
||||
if (write_limit_exceeded) {
|
||||
// Stop writing after the write limit is exceeded.
|
||||
// Don't close the file so we can print a stacktrace if necessary
|
||||
enabled = false;
|
||||
}
|
||||
file->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() override {
|
||||
file->Flush();
|
||||
}
|
||||
|
||||
void EnableForStacktrace() override {
|
||||
enabled = true;
|
||||
bytes_written = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<FS::IOFile> file;
|
||||
bool enabled = true;
|
||||
std::size_t bytes_written = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to Visual Studio's output window
|
||||
*/
|
||||
class DebuggerBackend final : public Backend {
|
||||
public:
|
||||
explicit DebuggerBackend() = default;
|
||||
|
||||
~DebuggerBackend() override = default;
|
||||
|
||||
void Write(const Entry& entry) override {
|
||||
#ifdef _WIN32
|
||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Flush() override {}
|
||||
|
||||
void EnableForStacktrace() override {}
|
||||
};
|
||||
|
||||
bool initialization_in_progress_suppress_logging = true;
|
||||
|
||||
/**
|
||||
* Static state as a singleton.
|
||||
*/
|
||||
class Impl {
|
||||
public:
|
||||
static Impl& Instance() {
|
||||
static Impl backend;
|
||||
return backend;
|
||||
if (!instance) {
|
||||
throw std::runtime_error("Using Logging instance before its initialization");
|
||||
}
|
||||
return *instance;
|
||||
}
|
||||
|
||||
static void Initialize() {
|
||||
if (instance) {
|
||||
LOG_WARNING(Log, "Reinitializing logging backend");
|
||||
return;
|
||||
}
|
||||
using namespace Common::FS;
|
||||
const auto& log_dir = GetYuzuPath(YuzuPath::LogDir);
|
||||
void(CreateDir(log_dir));
|
||||
Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter),
|
||||
Deleter);
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
Impl(const Impl&) = delete;
|
||||
@@ -46,74 +188,54 @@ public:
|
||||
Impl(Impl&&) = delete;
|
||||
Impl& operator=(Impl&&) = delete;
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string message) {
|
||||
message_queue.Push(
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
|
||||
}
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
backends.push_back(std::move(backend));
|
||||
}
|
||||
|
||||
void RemoveBackend(std::string_view backend_name) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
|
||||
std::erase_if(backends, [&backend_name](const auto& backend) {
|
||||
return backend_name == backend->GetName();
|
||||
});
|
||||
}
|
||||
|
||||
const Filter& GetGlobalFilter() const {
|
||||
return filter;
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& f) {
|
||||
filter = f;
|
||||
}
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name) {
|
||||
const auto it =
|
||||
std::find_if(backends.begin(), backends.end(),
|
||||
[&backend_name](const auto& i) { return backend_name == i->GetName(); });
|
||||
if (it == backends.end())
|
||||
return nullptr;
|
||||
return it->get();
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
color_console_backend.SetEnabled(enabled);
|
||||
}
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string message) {
|
||||
if (!filter.CheckMessage(log_class, log_level))
|
||||
return;
|
||||
const Entry& entry =
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
|
||||
message_queue.Push(entry);
|
||||
}
|
||||
|
||||
private:
|
||||
Impl() {
|
||||
backend_thread = std::thread([&] {
|
||||
Entry entry;
|
||||
auto write_logs = [&](Entry& e) {
|
||||
std::lock_guard lock{writing_mutex};
|
||||
for (const auto& backend : backends) {
|
||||
backend->Write(e);
|
||||
}
|
||||
};
|
||||
while (true) {
|
||||
entry = message_queue.PopWait();
|
||||
if (entry.final_entry) {
|
||||
break;
|
||||
}
|
||||
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.
|
||||
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)) {
|
||||
write_logs(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
||||
: filter{filter_}, file_backend{file_backend_filename}, backend_thread{std::thread([this] {
|
||||
Common::SetCurrentThreadName("yuzu:Log");
|
||||
Entry entry;
|
||||
const auto write_logs = [this, &entry]() {
|
||||
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
|
||||
};
|
||||
while (true) {
|
||||
entry = message_queue.PopWait();
|
||||
if (entry.final_entry) {
|
||||
break;
|
||||
}
|
||||
write_logs();
|
||||
}
|
||||
// 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.
|
||||
int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
|
||||
while (max_logs_to_write-- && message_queue.Pop(entry)) {
|
||||
write_logs();
|
||||
}
|
||||
})} {}
|
||||
|
||||
~Impl() {
|
||||
Entry entry;
|
||||
entry.final_entry = true;
|
||||
message_queue.Push(entry);
|
||||
StopBackendThread();
|
||||
}
|
||||
|
||||
void StopBackendThread() {
|
||||
Entry stop_entry{};
|
||||
stop_entry.final_entry = true;
|
||||
message_queue.Push(stop_entry);
|
||||
backend_thread.join();
|
||||
}
|
||||
|
||||
@@ -135,100 +257,51 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
std::mutex writing_mutex;
|
||||
std::thread backend_thread;
|
||||
std::vector<std::unique_ptr<Backend>> backends;
|
||||
MPSCQueue<Entry> message_queue;
|
||||
void ForEachBackend(auto lambda) {
|
||||
lambda(static_cast<Backend&>(debugger_backend));
|
||||
lambda(static_cast<Backend&>(color_console_backend));
|
||||
lambda(static_cast<Backend&>(file_backend));
|
||||
}
|
||||
|
||||
static void Deleter(Impl* ptr) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||
|
||||
Filter filter;
|
||||
DebuggerBackend debugger_backend{};
|
||||
ColorConsoleBackend color_console_backend{};
|
||||
FileBackend file_backend;
|
||||
|
||||
std::thread backend_thread;
|
||||
MPSCQueue<Entry> message_queue{};
|
||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ConsoleBackend::~ConsoleBackend() = default;
|
||||
|
||||
void ConsoleBackend::Write(const Entry& entry) {
|
||||
PrintMessage(entry);
|
||||
void Initialize() {
|
||||
Impl::Initialize();
|
||||
}
|
||||
|
||||
ColorConsoleBackend::~ColorConsoleBackend() = default;
|
||||
|
||||
void ColorConsoleBackend::Write(const Entry& entry) {
|
||||
PrintColoredMessage(entry);
|
||||
}
|
||||
|
||||
FileBackend::FileBackend(const std::filesystem::path& filename) {
|
||||
auto old_filename = filename;
|
||||
old_filename += ".old.txt";
|
||||
|
||||
// Existence checks are done within the functions themselves.
|
||||
// We don't particularly care if these succeed or not.
|
||||
FS::RemoveFile(old_filename);
|
||||
void(FS::RenameFile(filename, old_filename));
|
||||
|
||||
file =
|
||||
std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
|
||||
}
|
||||
|
||||
FileBackend::~FileBackend() = default;
|
||||
|
||||
void FileBackend::Write(const Entry& entry) {
|
||||
if (!file->IsOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace Common::Literals;
|
||||
// Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
|
||||
constexpr std::size_t MAX_BYTES_WRITTEN = 100_MiB;
|
||||
constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1_GiB;
|
||||
|
||||
const bool write_limit_exceeded =
|
||||
bytes_written > MAX_BYTES_WRITTEN_EXTENDED ||
|
||||
(bytes_written > MAX_BYTES_WRITTEN && !Settings::values.extended_logging);
|
||||
|
||||
// Close the file after the write limit is exceeded.
|
||||
if (write_limit_exceeded) {
|
||||
file->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
|
||||
if (entry.log_level >= Level::Error) {
|
||||
file->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
DebuggerBackend::~DebuggerBackend() = default;
|
||||
|
||||
void DebuggerBackend::Write(const Entry& entry) {
|
||||
#ifdef _WIN32
|
||||
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
|
||||
#endif
|
||||
void DisableLoggingInTests() {
|
||||
initialization_in_progress_suppress_logging = true;
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& filter) {
|
||||
Impl::Instance().SetGlobalFilter(filter);
|
||||
}
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend) {
|
||||
Impl::Instance().AddBackend(std::move(backend));
|
||||
}
|
||||
|
||||
void RemoveBackend(std::string_view backend_name) {
|
||||
Impl::Instance().RemoveBackend(backend_name);
|
||||
}
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name) {
|
||||
return Impl::Instance().GetBackend(backend_name);
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||
}
|
||||
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, const char* format,
|
||||
const fmt::format_args& args) {
|
||||
auto& instance = Impl::Instance();
|
||||
const auto& filter = instance.GetGlobalFilter();
|
||||
if (!filter.CheckMessage(log_class, log_level))
|
||||
return;
|
||||
|
||||
instance.PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, args));
|
||||
if (!initialization_in_progress_suppress_logging) {
|
||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||
fmt::vformat(format, args));
|
||||
}
|
||||
}
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -5,120 +5,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include "common/logging/filter.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace Common::FS {
|
||||
class IOFile;
|
||||
}
|
||||
|
||||
namespace Common::Log {
|
||||
|
||||
class Filter;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/// Initializes the logging system. This should be the first thing called in main.
|
||||
void Initialize();
|
||||
|
||||
virtual void SetFilter(const Filter& new_filter) {
|
||||
filter = new_filter;
|
||||
}
|
||||
virtual const char* GetName() const = 0;
|
||||
virtual void Write(const Entry& entry) = 0;
|
||||
|
||||
private:
|
||||
Filter filter;
|
||||
};
|
||||
void DisableLoggingInTests();
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr without any color commands
|
||||
*/
|
||||
class ConsoleBackend : public Backend {
|
||||
public:
|
||||
~ConsoleBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "console";
|
||||
}
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to stderr and with color
|
||||
*/
|
||||
class ColorConsoleBackend : public Backend {
|
||||
public:
|
||||
~ColorConsoleBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "color_console";
|
||||
}
|
||||
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to a file passed into the constructor
|
||||
*/
|
||||
class FileBackend : public Backend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename);
|
||||
~FileBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "file";
|
||||
}
|
||||
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
|
||||
void Write(const Entry& entry) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<FS::IOFile> file;
|
||||
std::size_t bytes_written = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Backend that writes to Visual Studio's output window
|
||||
*/
|
||||
class DebuggerBackend : public Backend {
|
||||
public:
|
||||
~DebuggerBackend() override;
|
||||
|
||||
static const char* Name() {
|
||||
return "debugger";
|
||||
}
|
||||
const char* GetName() const override {
|
||||
return Name();
|
||||
}
|
||||
void Write(const Entry& entry) override;
|
||||
};
|
||||
|
||||
void AddBackend(std::unique_ptr<Backend> backend);
|
||||
|
||||
void RemoveBackend(std::string_view backend_name);
|
||||
|
||||
Backend* GetBackend(std::string_view backend_name);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* The global filter will prevent any messages from even being processed if they are filtered.
|
||||
*/
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
} // namespace Common::Log
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -489,7 +489,7 @@ struct Values {
|
||||
std::chrono::seconds custom_rtc_differential;
|
||||
|
||||
BasicSetting<s32> current_user{0, "current_user"};
|
||||
RangedSetting<s32> language_index{1, 0, 16, "language_index"};
|
||||
RangedSetting<s32> language_index{1, 0, 17, "language_index"};
|
||||
RangedSetting<s32> region_index{1, 0, 6, "region_index"};
|
||||
RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"};
|
||||
RangedSetting<s32> sound_index{1, 0, 2, "sound_index"};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <bitset>
|
||||
#include <initializer_list>
|
||||
#include <xbyak.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <xbyak.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include "common/x64/xbyak_abi.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -84,8 +85,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
/*static*/ System System::s_instance;
|
||||
|
||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
const std::string& path) {
|
||||
// To account for split 00+01+etc files.
|
||||
@@ -425,6 +424,20 @@ struct System::Impl {
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
System::~System() = default;
|
||||
|
||||
System& System::GetInstance() {
|
||||
if (!s_instance) {
|
||||
throw std::runtime_error("Using System instance before its initialization");
|
||||
}
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void System::InitializeGlobalInstance() {
|
||||
if (s_instance) {
|
||||
throw std::runtime_error("Reinitializing Global System instance.");
|
||||
}
|
||||
s_instance = std::unique_ptr<System>(new System);
|
||||
}
|
||||
|
||||
CpuManager& System::GetCpuManager() {
|
||||
return impl->cpu_manager;
|
||||
}
|
||||
|
||||
@@ -120,9 +120,9 @@ public:
|
||||
* Gets the instance of the System singleton class.
|
||||
* @returns Reference to the instance of the System singleton class.
|
||||
*/
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() {
|
||||
return s_instance;
|
||||
}
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance();
|
||||
|
||||
static void InitializeGlobalInstance();
|
||||
|
||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||
enum class ResultStatus : u32 {
|
||||
@@ -393,7 +393,7 @@ private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
static System s_instance;
|
||||
inline static std::unique_ptr<System> s_instance{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -261,20 +261,23 @@ struct KernelCore::Impl {
|
||||
current_process = process;
|
||||
}
|
||||
|
||||
/// Creates a new host thread ID, should only be called by GetHostThreadId
|
||||
u32 AllocateHostThreadId(std::optional<std::size_t> core_id) {
|
||||
if (core_id) {
|
||||
// The first for slots are reserved for CPU core threads
|
||||
ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
return static_cast<u32>(*core_id);
|
||||
} else {
|
||||
return next_host_thread_id++;
|
||||
static inline thread_local u32 host_thread_id = UINT32_MAX;
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId(std::size_t core_id) {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
// The first four slots are reserved for CPU core threads
|
||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||
host_thread_id = static_cast<u32>(core_id);
|
||||
}
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||
u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) {
|
||||
const thread_local auto host_thread_id{AllocateHostThreadId(core_id)};
|
||||
u32 GetHostThreadId() {
|
||||
if (host_thread_id == UINT32_MAX) {
|
||||
host_thread_id = next_host_thread_id++;
|
||||
}
|
||||
return host_thread_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,14 +298,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
|
||||
if (IR::IsGeneric(attr)) {
|
||||
const u32 index{IR::GenericAttributeIndex(attr)};
|
||||
const std::optional<AttrInfo> type{AttrTypes(ctx, index)};
|
||||
if (!type) {
|
||||
// Attribute is disabled
|
||||
if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index, element)) {
|
||||
// Attribute is disabled or varying component is not written
|
||||
return ctx.Const(element == 3 ? 1.0f : 0.0f);
|
||||
}
|
||||
if (!ctx.runtime_info.previous_stage_stores.Generic(index, element)) {
|
||||
// Varying component is not written
|
||||
return ctx.Const(type && element == 3 ? 1.0f : 0.0f);
|
||||
}
|
||||
const Id generic_id{ctx.input_generics.at(index)};
|
||||
const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))};
|
||||
const Id value{ctx.OpLoad(type->id, pointer)};
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <math.h>
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/param_package.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
TEST_CASE("ParamPackage", "[common]") {
|
||||
Common::Log::DisableLoggingInTests();
|
||||
ParamPackage original{
|
||||
{"abc", "xyz"},
|
||||
{"def", "42"},
|
||||
|
||||
@@ -742,6 +742,7 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() {
|
||||
uncomp_writer.WriteDeltaQ(current_frame_info.uv_dc_delta_q);
|
||||
uncomp_writer.WriteDeltaQ(current_frame_info.uv_ac_delta_q);
|
||||
|
||||
ASSERT(!current_frame_info.segment_enabled);
|
||||
uncomp_writer.WriteBit(false); // Segmentation enabled (TODO).
|
||||
|
||||
const s32 min_tile_cols_log2 = CalcMinLog2TileCols(current_frame_info.frame_size.width);
|
||||
|
||||
@@ -22,7 +22,7 @@ struct Vp9FrameDimensions {
|
||||
};
|
||||
static_assert(sizeof(Vp9FrameDimensions) == 0x8, "Vp9 Vp9FrameDimensions is an invalid size");
|
||||
|
||||
enum FrameFlags : u32 {
|
||||
enum class FrameFlags : u32 {
|
||||
IsKeyFrame = 1 << 0,
|
||||
LastFrameIsKeyFrame = 1 << 1,
|
||||
FrameSizeChanged = 1 << 2,
|
||||
@@ -30,6 +30,7 @@ enum FrameFlags : u32 {
|
||||
LastShowFrame = 1 << 4,
|
||||
IntraOnly = 1 << 5,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(FrameFlags)
|
||||
|
||||
enum class TxSize {
|
||||
Tx4x4 = 0, // 4x4 transform
|
||||
@@ -92,44 +93,34 @@ struct Vp9EntropyProbs {
|
||||
static_assert(sizeof(Vp9EntropyProbs) == 0x7B4, "Vp9EntropyProbs is an invalid size");
|
||||
|
||||
struct Vp9PictureInfo {
|
||||
bool is_key_frame;
|
||||
bool intra_only;
|
||||
bool last_frame_was_key;
|
||||
bool frame_size_changed;
|
||||
bool error_resilient_mode;
|
||||
bool last_frame_shown;
|
||||
bool show_frame;
|
||||
u32 bitstream_size;
|
||||
std::array<u64, 4> frame_offsets;
|
||||
std::array<s8, 4> ref_frame_sign_bias;
|
||||
s32 base_q_index;
|
||||
s32 y_dc_delta_q;
|
||||
s32 uv_dc_delta_q;
|
||||
s32 uv_ac_delta_q;
|
||||
bool lossless;
|
||||
s32 transform_mode;
|
||||
bool allow_high_precision_mv;
|
||||
s32 interp_filter;
|
||||
s32 reference_mode;
|
||||
s8 comp_fixed_ref;
|
||||
std::array<s8, 2> comp_var_ref;
|
||||
s32 log2_tile_cols;
|
||||
s32 log2_tile_rows;
|
||||
bool segment_enabled;
|
||||
bool segment_map_update;
|
||||
bool segment_map_temporal_update;
|
||||
s32 segment_abs_delta;
|
||||
std::array<u32, 8> segment_feature_enable;
|
||||
std::array<std::array<s16, 4>, 8> segment_feature_data;
|
||||
bool mode_ref_delta_enabled;
|
||||
bool use_prev_in_find_mv_refs;
|
||||
std::array<s8, 4> ref_deltas;
|
||||
std::array<s8, 2> mode_deltas;
|
||||
Vp9EntropyProbs entropy;
|
||||
Vp9FrameDimensions frame_size;
|
||||
u8 first_level;
|
||||
u8 sharpness_level;
|
||||
u32 bitstream_size;
|
||||
std::array<u64, 4> frame_offsets;
|
||||
std::array<bool, 4> refresh_frame;
|
||||
bool is_key_frame;
|
||||
bool intra_only;
|
||||
bool last_frame_was_key;
|
||||
bool error_resilient_mode;
|
||||
bool last_frame_shown;
|
||||
bool show_frame;
|
||||
bool lossless;
|
||||
bool allow_high_precision_mv;
|
||||
bool segment_enabled;
|
||||
bool mode_ref_delta_enabled;
|
||||
};
|
||||
|
||||
struct Vp9FrameContainer {
|
||||
@@ -145,7 +136,7 @@ struct PictureInfo {
|
||||
Vp9FrameDimensions golden_frame_size; ///< 0x50
|
||||
Vp9FrameDimensions alt_frame_size; ///< 0x58
|
||||
Vp9FrameDimensions current_frame_size; ///< 0x60
|
||||
u32 vp9_flags; ///< 0x68
|
||||
FrameFlags vp9_flags; ///< 0x68
|
||||
std::array<s8, 4> ref_frame_sign_bias; ///< 0x6C
|
||||
u8 first_level; ///< 0x70
|
||||
u8 sharpness_level; ///< 0x71
|
||||
@@ -158,60 +149,43 @@ struct PictureInfo {
|
||||
u8 allow_high_precision_mv; ///< 0x78
|
||||
u8 interp_filter; ///< 0x79
|
||||
u8 reference_mode; ///< 0x7A
|
||||
s8 comp_fixed_ref; ///< 0x7B
|
||||
std::array<s8, 2> comp_var_ref; ///< 0x7C
|
||||
INSERT_PADDING_BYTES_NOINIT(3); ///< 0x7B
|
||||
u8 log2_tile_cols; ///< 0x7E
|
||||
u8 log2_tile_rows; ///< 0x7F
|
||||
Segmentation segmentation; ///< 0x80
|
||||
LoopFilter loop_filter; ///< 0xE4
|
||||
INSERT_PADDING_BYTES_NOINIT(5); ///< 0xEB
|
||||
u32 surface_params; ///< 0xF0
|
||||
INSERT_PADDING_WORDS_NOINIT(3); ///< 0xF4
|
||||
INSERT_PADDING_BYTES_NOINIT(21); ///< 0xEB
|
||||
|
||||
[[nodiscard]] Vp9PictureInfo Convert() const {
|
||||
return {
|
||||
.is_key_frame = (vp9_flags & FrameFlags::IsKeyFrame) != 0,
|
||||
.intra_only = (vp9_flags & FrameFlags::IntraOnly) != 0,
|
||||
.last_frame_was_key = (vp9_flags & FrameFlags::LastFrameIsKeyFrame) != 0,
|
||||
.frame_size_changed = (vp9_flags & FrameFlags::FrameSizeChanged) != 0,
|
||||
.error_resilient_mode = (vp9_flags & FrameFlags::ErrorResilientMode) != 0,
|
||||
.last_frame_shown = (vp9_flags & FrameFlags::LastShowFrame) != 0,
|
||||
.show_frame = true,
|
||||
.bitstream_size = bitstream_size,
|
||||
.frame_offsets{},
|
||||
.ref_frame_sign_bias = ref_frame_sign_bias,
|
||||
.base_q_index = base_q_index,
|
||||
.y_dc_delta_q = y_dc_delta_q,
|
||||
.uv_dc_delta_q = uv_dc_delta_q,
|
||||
.uv_ac_delta_q = uv_ac_delta_q,
|
||||
.lossless = lossless != 0,
|
||||
.transform_mode = tx_mode,
|
||||
.allow_high_precision_mv = allow_high_precision_mv != 0,
|
||||
.interp_filter = interp_filter,
|
||||
.reference_mode = reference_mode,
|
||||
.comp_fixed_ref = comp_fixed_ref,
|
||||
.comp_var_ref = comp_var_ref,
|
||||
.log2_tile_cols = log2_tile_cols,
|
||||
.log2_tile_rows = log2_tile_rows,
|
||||
.segment_enabled = segmentation.enabled != 0,
|
||||
.segment_map_update = segmentation.update_map != 0,
|
||||
.segment_map_temporal_update = segmentation.temporal_update != 0,
|
||||
.segment_abs_delta = segmentation.abs_delta,
|
||||
.segment_feature_enable = segmentation.feature_mask,
|
||||
.segment_feature_data = segmentation.feature_data,
|
||||
.mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0,
|
||||
.use_prev_in_find_mv_refs = !(vp9_flags == (FrameFlags::ErrorResilientMode)) &&
|
||||
!(vp9_flags == (FrameFlags::FrameSizeChanged)) &&
|
||||
!(vp9_flags == (FrameFlags::IntraOnly)) &&
|
||||
(vp9_flags == (FrameFlags::LastShowFrame)) &&
|
||||
!(vp9_flags == (FrameFlags::LastFrameIsKeyFrame)),
|
||||
.ref_deltas = loop_filter.ref_deltas,
|
||||
.mode_deltas = loop_filter.mode_deltas,
|
||||
.entropy{},
|
||||
.frame_size = current_frame_size,
|
||||
.first_level = first_level,
|
||||
.sharpness_level = sharpness_level,
|
||||
.bitstream_size = bitstream_size,
|
||||
.frame_offsets{},
|
||||
.refresh_frame{},
|
||||
.is_key_frame = True(vp9_flags & FrameFlags::IsKeyFrame),
|
||||
.intra_only = True(vp9_flags & FrameFlags::IntraOnly),
|
||||
.last_frame_was_key = True(vp9_flags & FrameFlags::LastFrameIsKeyFrame),
|
||||
.error_resilient_mode = True(vp9_flags & FrameFlags::ErrorResilientMode),
|
||||
.last_frame_shown = True(vp9_flags & FrameFlags::LastShowFrame),
|
||||
.show_frame = true,
|
||||
.lossless = lossless != 0,
|
||||
.allow_high_precision_mv = allow_high_precision_mv != 0,
|
||||
.segment_enabled = segmentation.enabled != 0,
|
||||
.mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -316,7 +290,6 @@ ASSERT_POSITION(last_frame_size, 0x48);
|
||||
ASSERT_POSITION(first_level, 0x70);
|
||||
ASSERT_POSITION(segmentation, 0x80);
|
||||
ASSERT_POSITION(loop_filter, 0xE4);
|
||||
ASSERT_POSITION(surface_params, 0xF0);
|
||||
#undef ASSERT_POSITION
|
||||
|
||||
#define ASSERT_POSITION(field_name, position) \
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <xbyak.h>
|
||||
#include <xbyak/xbyak.h>
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/x64/xbyak_abi.h"
|
||||
|
||||
@@ -463,6 +463,7 @@ std::vector<std::pair<GPUVAddr, std::size_t>> MemoryManager::GetSubmappedRange(
|
||||
++page_index;
|
||||
page_offset = 0;
|
||||
remaining_size -= num_bytes;
|
||||
old_page_addr = page_addr;
|
||||
}
|
||||
split();
|
||||
return result;
|
||||
|
||||
@@ -281,7 +281,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxw
|
||||
.supported_spirv = device.IsKhrSpirv1_4Supported() ? 0x00010400U : 0x00010000U,
|
||||
.unified_descriptor_binding = true,
|
||||
.support_descriptor_aliasing = true,
|
||||
.support_int8 = true,
|
||||
.support_int8 = device.IsInt8Supported(),
|
||||
.support_int16 = device.IsShaderInt16Supported(),
|
||||
.support_int64 = device.IsShaderInt64Supported(),
|
||||
.support_vertex_instance_id = false,
|
||||
|
||||
@@ -159,7 +159,7 @@ static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size");
|
||||
return {raw, raw};
|
||||
} else {
|
||||
const Tegra::Texture::TextureHandle handle{raw};
|
||||
return {handle.tic_id, via_header_index ? handle.tic_id : handle.tsc_id};
|
||||
return {handle.tic_id, handle.tsc_id};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,18 +368,21 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
};
|
||||
SetNext(next, demote);
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8;
|
||||
if (is_float16_supported) {
|
||||
float16_int8 = {
|
||||
if (is_int8_supported || is_float16_supported) {
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR,
|
||||
.pNext = nullptr,
|
||||
.shaderFloat16 = true,
|
||||
.shaderInt8 = false,
|
||||
.shaderFloat16 = is_float16_supported,
|
||||
.shaderInt8 = is_int8_supported,
|
||||
};
|
||||
SetNext(next, float16_int8);
|
||||
} else {
|
||||
}
|
||||
if (!is_float16_supported) {
|
||||
LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively");
|
||||
}
|
||||
if (!is_int8_supported) {
|
||||
LOG_INFO(Render_Vulkan, "Device doesn't support int8 natively");
|
||||
}
|
||||
|
||||
if (!nv_viewport_swizzle) {
|
||||
LOG_INFO(Render_Vulkan, "Device doesn't support viewport swizzles");
|
||||
@@ -909,6 +912,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||
|
||||
physical.GetFeatures2KHR(features);
|
||||
is_float16_supported = float16_int8_features.shaderFloat16;
|
||||
is_int8_supported = float16_int8_features.shaderInt8;
|
||||
extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
|
||||
}
|
||||
if (has_ext_subgroup_size_control) {
|
||||
|
||||
@@ -139,11 +139,16 @@ public:
|
||||
return is_optimal_astc_supported;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports float16 natively
|
||||
/// Returns true if the device supports float16 natively.
|
||||
bool IsFloat16Supported() const {
|
||||
return is_float16_supported;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports int8 natively.
|
||||
bool IsInt8Supported() const {
|
||||
return is_int8_supported;
|
||||
}
|
||||
|
||||
/// Returns true if the device warp size can potentially be bigger than guest's warp size.
|
||||
bool IsWarpSizePotentiallyBiggerThanGuest() const {
|
||||
return is_warp_potentially_bigger;
|
||||
@@ -367,7 +372,8 @@ private:
|
||||
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
||||
u32 max_push_descriptors{}; ///< Maximum number of push descriptors
|
||||
bool is_optimal_astc_supported{}; ///< Support for native ASTC.
|
||||
bool is_float16_supported{}; ///< Support for float16 arithmetics.
|
||||
bool is_float16_supported{}; ///< Support for float16 arithmetic.
|
||||
bool is_int8_supported{}; ///< Support for int8 arithmetic.
|
||||
bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest.
|
||||
bool is_formatless_image_load_supported{}; ///< Support for shader image read without format.
|
||||
bool is_depth_bounds_supported{}; ///< Support for depth bounds.
|
||||
|
||||
@@ -182,7 +182,14 @@ if (ENABLE_QT_TRANSLATION)
|
||||
# Update source TS file if enabled
|
||||
if (GENERATE_QT_TRANSLATION)
|
||||
get_target_property(SRCS yuzu SOURCES)
|
||||
qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts)
|
||||
qt5_create_translation(QM_FILES
|
||||
${SRCS}
|
||||
${UIS}
|
||||
${YUZU_QT_LANGUAGES}/en.ts
|
||||
OPTIONS
|
||||
-source-language en_US
|
||||
-target-language en_US
|
||||
)
|
||||
add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -438,7 +438,7 @@ void QtSoftwareKeyboardDialog::ShowInlineKeyboard(
|
||||
initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags;
|
||||
initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button;
|
||||
initialize_parameters.enable_return_button = appear_parameters.enable_return_button;
|
||||
initialize_parameters.disable_cancel_button = initialize_parameters.disable_cancel_button;
|
||||
initialize_parameters.disable_cancel_button = appear_parameters.disable_cancel_button;
|
||||
|
||||
SetKeyboardType();
|
||||
SetControllerImage();
|
||||
|
||||
@@ -647,18 +647,18 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
|
||||
// Face buttons
|
||||
p.setPen(colors.outline);
|
||||
button_color = colors.button;
|
||||
DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius);
|
||||
DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius);
|
||||
DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius);
|
||||
DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius);
|
||||
DrawCircleButton(p, face_center + QPointF(face_distance, 0), button_values[A], face_radius);
|
||||
DrawCircleButton(p, face_center + QPointF(0, face_distance), button_values[B], face_radius);
|
||||
DrawCircleButton(p, face_center + QPointF(0, -face_distance), button_values[X], face_radius);
|
||||
DrawCircleButton(p, face_center + QPointF(-face_distance, 0), button_values[Y], face_radius);
|
||||
|
||||
// Face buttons text
|
||||
p.setPen(colors.transparent);
|
||||
p.setBrush(colors.font);
|
||||
DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size);
|
||||
DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size);
|
||||
DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size);
|
||||
DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
|
||||
DrawSymbol(p, face_center + QPointF(face_distance, 0), Symbol::A, text_size);
|
||||
DrawSymbol(p, face_center + QPointF(0, face_distance), Symbol::B, text_size);
|
||||
DrawSymbol(p, face_center + QPointF(0, -face_distance), Symbol::X, text_size);
|
||||
DrawSymbol(p, face_center + QPointF(-face_distance, 1), Symbol::Y, text_size);
|
||||
|
||||
// D-pad constants
|
||||
const QPointF dpad_center = center + QPoint(-171, 8);
|
||||
@@ -669,18 +669,20 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
|
||||
// D-pad buttons
|
||||
p.setPen(colors.outline);
|
||||
button_color = colors.button;
|
||||
DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPointF(dpad_distance, 0), button_values[DRight],
|
||||
dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPointF(0, dpad_distance), button_values[DDown], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPointF(0, -dpad_distance), button_values[DUp], dpad_radius);
|
||||
DrawCircleButton(p, dpad_center + QPointF(-dpad_distance, 0), button_values[DLeft],
|
||||
dpad_radius);
|
||||
|
||||
// D-pad arrows
|
||||
p.setPen(colors.font2);
|
||||
p.setBrush(colors.font2);
|
||||
DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPointF(dpad_distance, 0), Direction::Right, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPointF(0, dpad_distance), Direction::Down, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPointF(0, -dpad_distance), Direction::Up, dpad_arrow_size);
|
||||
DrawArrow(p, dpad_center + QPointF(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
|
||||
|
||||
// ZL and ZR buttons
|
||||
p.setPen(colors.outline);
|
||||
|
||||
@@ -21,6 +21,7 @@ void ToggleConsole() {
|
||||
console_shown = UISettings::values.show_console.GetValue();
|
||||
}
|
||||
|
||||
using namespace Common::Log;
|
||||
#if defined(_WIN32) && !defined(_DEBUG)
|
||||
FILE* temp;
|
||||
if (UISettings::values.show_console) {
|
||||
@@ -29,24 +30,20 @@ void ToggleConsole() {
|
||||
freopen_s(&temp, "CONIN$", "r", stdin);
|
||||
freopen_s(&temp, "CONOUT$", "w", stdout);
|
||||
freopen_s(&temp, "CONOUT$", "w", stderr);
|
||||
Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
|
||||
SetColorConsoleBackendEnabled(true);
|
||||
}
|
||||
} else {
|
||||
if (FreeConsole()) {
|
||||
// In order to close the console, we have to also detach the streams on it.
|
||||
// Just redirect them to NUL if there is no console window
|
||||
Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
|
||||
SetColorConsoleBackendEnabled(false);
|
||||
freopen_s(&temp, "NUL", "r", stdin);
|
||||
freopen_s(&temp, "NUL", "w", stdout);
|
||||
freopen_s(&temp, "NUL", "w", stderr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (UISettings::values.show_console) {
|
||||
Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
|
||||
} else {
|
||||
Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
|
||||
}
|
||||
SetColorConsoleBackendEnabled(UISettings::values.show_console.GetValue());
|
||||
#endif
|
||||
}
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -175,21 +175,6 @@ void GMainWindow::ShowTelemetryCallout() {
|
||||
|
||||
const int GMainWindow::max_recent_files_item;
|
||||
|
||||
static void InitializeLogging() {
|
||||
using namespace Common;
|
||||
|
||||
Log::Filter log_filter;
|
||||
log_filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Log::SetGlobalFilter(log_filter);
|
||||
|
||||
const auto log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir);
|
||||
void(FS::CreateDir(log_dir));
|
||||
Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir / LOG_FILE));
|
||||
#ifdef _WIN32
|
||||
Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void RemoveCachedContents() {
|
||||
const auto cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir);
|
||||
const auto offline_fonts = cache_dir / "fonts";
|
||||
@@ -207,8 +192,7 @@ GMainWindow::GMainWindow()
|
||||
: input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
|
||||
config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
||||
provider{std::make_unique<FileSys::ManualContentProvider>()} {
|
||||
InitializeLogging();
|
||||
|
||||
Common::Log::Initialize();
|
||||
LoadTranslation();
|
||||
|
||||
setAcceptDrops(true);
|
||||
@@ -3437,6 +3421,7 @@ int main(int argc, char* argv[]) {
|
||||
// generating shaders
|
||||
setlocale(LC_ALL, "C");
|
||||
|
||||
Core::System::InitializeGlobalInstance();
|
||||
GMainWindow main_window;
|
||||
// After settings have been loaded by GMainWindow, apply the filter
|
||||
main_window.show();
|
||||
|
||||
@@ -74,31 +74,14 @@ static void PrintVersion() {
|
||||
std::cout << "yuzu " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
|
||||
}
|
||||
|
||||
static void InitializeLogging() {
|
||||
using namespace Common;
|
||||
|
||||
Log::Filter log_filter(Log::Level::Debug);
|
||||
log_filter.ParseFilterString(static_cast<std::string>(Settings::values.log_filter));
|
||||
Log::SetGlobalFilter(log_filter);
|
||||
|
||||
Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
|
||||
|
||||
const auto& log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir);
|
||||
void(FS::CreateDir(log_dir));
|
||||
Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir / LOG_FILE));
|
||||
#ifdef _WIN32
|
||||
Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Application entry point
|
||||
int main(int argc, char** argv) {
|
||||
Common::Log::Initialize();
|
||||
Common::Log::SetColorConsoleBackendEnabled(true);
|
||||
Common::DetachedTasks detached_tasks;
|
||||
Config config;
|
||||
|
||||
int option_index = 0;
|
||||
|
||||
InitializeLogging();
|
||||
#ifdef _WIN32
|
||||
int argc_w;
|
||||
auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
|
||||
@@ -163,6 +146,7 @@ int main(int argc, char** argv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Core::System::InitializeGlobalInstance();
|
||||
auto& system{Core::System::GetInstance()};
|
||||
InputCommon::InputSubsystem input_subsystem;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user