mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-14 12:56:09 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed556a9053 | |||
| 54046ac60e |
+19
-5
@@ -41,6 +41,19 @@ namespace Common::Log {
|
||||
|
||||
namespace {
|
||||
|
||||
/// @brief 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::string_view thread_name;
|
||||
std::string message;
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class{};
|
||||
Level log_level{};
|
||||
const char* filename = nullptr;
|
||||
const char* function = nullptr;
|
||||
unsigned int line_num = 0;
|
||||
};
|
||||
|
||||
/// @brief Returns the name of the passed log class as a C-string. Subclasses are separated by periods
|
||||
/// instead of underscores as in the enumeration.
|
||||
/// @note GetClassName is a macro defined by Windows.h, grrr...
|
||||
@@ -79,7 +92,7 @@ std::string FormatLogMessage(const Entry& entry) noexcept {
|
||||
auto const time_fractional = uint32_t(entry.timestamp.count() % 1000000);
|
||||
auto const class_name = GetLogClassName(entry.log_class);
|
||||
auto const level_name = GetLevelName(entry.log_level);
|
||||
return fmt::format("[{:4d}.{:06d}] {} <{}> {}:{}:{}: {}", time_seconds, time_fractional, class_name, level_name, entry.filename, entry.line_num, entry.function, entry.message);
|
||||
return fmt::format("[{:4d}.{:06d}] {} <{}> (eden:{}) {}:{}:{}: {}", time_seconds, time_fractional, class_name, level_name, entry.thread_name.data(), entry.filename, entry.line_num, entry.function, entry.message);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -165,7 +178,7 @@ struct Backend {
|
||||
};
|
||||
|
||||
/// @brief Formatting specifier (to use with printf) of the equivalent fmt::format() expression
|
||||
#define CCB_PRINTF_FMT "[%4d.%06d] %s <%s> %s:%u:%s: %s"
|
||||
#define CCB_PRINTF_FMT "[%4d.%06d] %s <%s> (eden:%s) %s:%u:%s: %s"
|
||||
|
||||
/// @brief Instead of using fmt::format() just use the system's formatting capabilities directly
|
||||
struct DirectFormatArgs {
|
||||
@@ -208,7 +221,7 @@ struct ColorConsoleBackend final : public Backend {
|
||||
}());
|
||||
SetConsoleTextAttribute(console_handle, color);
|
||||
auto const df = GetDirectFormatArgs(entry);
|
||||
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
std::fprintf(stdout, CCB_PRINTF_FMT "\n", df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.thread_name.data(), entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
}
|
||||
}
|
||||
void Flush() noexcept override {}
|
||||
@@ -234,7 +247,7 @@ struct ColorConsoleBackend final : public Backend {
|
||||
}
|
||||
}();
|
||||
auto const df = GetDirectFormatArgs(entry);
|
||||
std::fprintf(stdout, color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
std::fprintf(stdout, color_str, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.thread_name.data(), entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
#undef ESC
|
||||
}
|
||||
}
|
||||
@@ -338,7 +351,7 @@ struct LogcatBackend : public Backend {
|
||||
}
|
||||
}();
|
||||
auto const df = GetDirectFormatArgs(entry);
|
||||
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
__android_log_print(android_log_priority, "YuzuNative", CCB_PRINTF_FMT, df.time_seconds, df.time_fractional, df.class_name, df.level_name, entry.thread_name.data(), entry.filename, entry.line_num, entry.function, entry.message.c_str());
|
||||
}
|
||||
void Flush() noexcept override {}
|
||||
};
|
||||
@@ -421,6 +434,7 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, u
|
||||
auto const flush = ::Settings::values.log_flush_line.GetValue();
|
||||
logging_instance->ForEachBackend([=](Backend& backend) {
|
||||
backend.Write(Entry{
|
||||
.thread_name = Common::GetCurrentThreadName(),
|
||||
.message = fmt::vformat(format, args),
|
||||
.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - logging_instance->time_origin),
|
||||
.log_class = log_class,
|
||||
|
||||
@@ -140,25 +140,4 @@ void Stop();
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
|
||||
/// @brief 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::string message;
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class{};
|
||||
Level log_level{};
|
||||
const char* filename = nullptr;
|
||||
const char* function = nullptr;
|
||||
unsigned int line_num = 0;
|
||||
};
|
||||
|
||||
/// Formats a log entry into the provided text buffer.
|
||||
std::string FormatLogMessage(const Entry& entry) noexcept;
|
||||
|
||||
/// Prints the same message as `PrintMessage`, but colored according to the severity level.
|
||||
void PrintColoredMessage(const Entry& entry) noexcept;
|
||||
|
||||
/// Formats and prints a log entry to the android logcat.
|
||||
void PrintMessageToLogcat(const Entry& entry) noexcept;
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
+13
-1
@@ -52,6 +52,13 @@
|
||||
|
||||
namespace Common {
|
||||
|
||||
// The use of TLS is justified as it is faster than using pthread_* functions
|
||||
// and generally will be better long term... yeah %fs/%gs reloads aren't great
|
||||
// but it's better than doing a potential call-stack-fuckery...
|
||||
thread_local struct {
|
||||
std::string name{};
|
||||
} per_thread_data = {};
|
||||
|
||||
void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||
#ifdef _WIN32
|
||||
int windows_priority = [&]() {
|
||||
@@ -96,7 +103,7 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* name) {
|
||||
void SetCurrentThreadName(const char* name) noexcept {
|
||||
#ifdef _MSC_VER
|
||||
// Sets the debugger-visible name of the current thread.
|
||||
if (auto pf = (decltype(&SetThreadDescription))(void*)GetProcAddress(GetModuleHandle(TEXT("KernelBase.dll")), "SetThreadDescription"); pf)
|
||||
@@ -130,6 +137,11 @@ void SetCurrentThreadName(const char* name) {
|
||||
#else
|
||||
pthread_setname_np(pthread_self(), name);
|
||||
#endif
|
||||
per_thread_data.name = std::string{name};
|
||||
}
|
||||
|
||||
std::string_view GetCurrentThreadName() noexcept {
|
||||
return per_thread_data.name;
|
||||
}
|
||||
|
||||
void PinCurrentThreadToPerformanceCore(size_t core_id) {
|
||||
|
||||
+2
-1
@@ -100,7 +100,8 @@ enum class ThreadPriority : u32 {
|
||||
};
|
||||
|
||||
void SetCurrentThreadPriority(ThreadPriority new_priority);
|
||||
void SetCurrentThreadName(const char* name);
|
||||
void SetCurrentThreadName(const char* name) noexcept;
|
||||
std::string_view GetCurrentThreadName() noexcept;
|
||||
void PinCurrentThreadToPerformanceCore(size_t core_id);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
+83
-79
@@ -417,14 +417,6 @@ void HLE_TransformFeedbackSetup::Execute(Core::System& system, Engines::Maxwell3
|
||||
default: return std::monostate{};
|
||||
}
|
||||
}
|
||||
[[nodiscard]] inline bool CanBeHLEProgram(u64 hash) noexcept {
|
||||
switch (hash) {
|
||||
#define HLE_MACRO_ELEM(HASH, TY, VAL) case HASH: return true;
|
||||
HLE_MACRO_LIST
|
||||
#undef HLE_MACRO_ELEM
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MacroInterpreterImpl::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span<const u32> params, u32 method) {
|
||||
Reset();
|
||||
@@ -1345,80 +1337,92 @@ static void Dump(u64 hash, std::span<const u32> code, bool decompiled = false) {
|
||||
macro_file.write(reinterpret_cast<const char*>(code.data()), code.size_bytes());
|
||||
}
|
||||
|
||||
void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span<const u32> parameters) {
|
||||
auto const execute_variant = [&system, &maxwell3d, ¶meters, method](AnyCachedMacro& acm) {
|
||||
if (auto a = std::get_if<HLE_DrawArraysIndirect>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_DrawIndexedIndirect>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_MultiDrawIndexedIndirectCount>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_MultiLayerClear>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_C713C83D8F63CCF3>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_D7333D26E0A93EDE>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_BindShader>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_SetRasterBoundingBox>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_ClearConstBuffer>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_ClearMemory>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_TransformFeedbackSetup>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<HLE_DrawIndirectByteCount>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<MacroInterpreterImpl>(&acm))
|
||||
return a->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto a = std::get_if<std::unique_ptr<DynamicCachedMacro>>(&acm))
|
||||
return a->get()->Execute(system, maxwell3d, parameters, method);
|
||||
};
|
||||
if (auto const it = macro_cache.find(method); it != macro_cache.end()) {
|
||||
auto& ci = it->second;
|
||||
if (!CanBeHLEProgram(ci.hash) || Settings::values.disable_macro_hle)
|
||||
maxwell3d.RefreshParameters(); //LLE must reload parameters
|
||||
execute_variant(ci.program);
|
||||
} else {
|
||||
// Macro not compiled, check if it's uploaded and if so, compile it
|
||||
std::optional<u32> mid_method;
|
||||
const auto macro_code = uploaded_macro_code.find(method);
|
||||
if (macro_code == uploaded_macro_code.end()) {
|
||||
for (const auto& [method_base, code] : uploaded_macro_code) {
|
||||
if (method >= method_base && (method - method_base) < code.size()) {
|
||||
mid_method = method_base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!mid_method.has_value()) {
|
||||
ASSERT_MSG(false, "Macro 0x{0:x} was not uploaded", method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto& ci = macro_cache[method];
|
||||
if (mid_method) {
|
||||
const auto& macro_cached = uploaded_macro_code[mid_method.value()];
|
||||
const auto rebased_method = method - mid_method.value();
|
||||
auto& code = uploaded_macro_code[method];
|
||||
code.resize(macro_cached.size() - rebased_method);
|
||||
std::memcpy(code.data(), macro_cached.data() + rebased_method, code.size() * sizeof(u32));
|
||||
ci.hash = Common::HashValue(code);
|
||||
ci.program = Compile(system, maxwell3d, code);
|
||||
} else {
|
||||
ci.program = Compile(system, maxwell3d, macro_code->second);
|
||||
ci.hash = Common::HashValue(macro_code->second);
|
||||
}
|
||||
if (CanBeHLEProgram(ci.hash) && !Settings::values.disable_macro_hle) {
|
||||
ci.program = GetHLEProgram(ci.hash);
|
||||
} else {
|
||||
void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method,
|
||||
std::span<const u32> parameters) {
|
||||
const auto execute_variant = [&system, &maxwell3d, ¶meters,
|
||||
method](AnyCachedMacro& cached) {
|
||||
if (std::holds_alternative<MacroInterpreterImpl>(cached) ||
|
||||
std::holds_alternative<std::unique_ptr<DynamicCachedMacro>>(cached) ||
|
||||
Settings::values.disable_macro_hle) {
|
||||
maxwell3d.RefreshParameters();
|
||||
}
|
||||
execute_variant(ci.program);
|
||||
if (Settings::values.dump_macros) {
|
||||
Dump(ci.hash, macro_code->second, !std::holds_alternative<std::monostate>(ci.program));
|
||||
|
||||
if (auto program = std::get_if<HLE_DrawArraysIndirect>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_DrawIndexedIndirect>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_MultiDrawIndexedIndirectCount>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_MultiLayerClear>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_C713C83D8F63CCF3>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_D7333D26E0A93EDE>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_BindShader>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_SetRasterBoundingBox>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_ClearConstBuffer>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_ClearMemory>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_TransformFeedbackSetup>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<HLE_DrawIndirectByteCount>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<MacroInterpreterImpl>(&cached))
|
||||
return program->Execute(system, maxwell3d, parameters, method);
|
||||
if (auto program = std::get_if<std::unique_ptr<DynamicCachedMacro>>(&cached))
|
||||
return program->get()->Execute(system, maxwell3d, parameters, method);
|
||||
|
||||
UNREACHABLE();
|
||||
};
|
||||
if (auto const it = macro_cache.find(method); it != macro_cache.end()) {
|
||||
execute_variant(it->second.program);
|
||||
return;
|
||||
}
|
||||
|
||||
// Macro not compiled, check if it's uploaded and if so, compile it
|
||||
std::span<const u32> code;
|
||||
auto macro_code = uploaded_macro_code.find(method);
|
||||
if (macro_code == uploaded_macro_code.end()) {
|
||||
std::optional<u32> mid_method;
|
||||
for (const auto& [method_base, uploaded_code] : uploaded_macro_code) {
|
||||
if (method >= method_base && (method - method_base) < uploaded_code.size()) {
|
||||
mid_method = method_base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!mid_method) {
|
||||
ASSERT_MSG(false, "Macro 0x{0:x} was not uploaded", method);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto source = uploaded_macro_code.find(*mid_method);
|
||||
ASSERT(source != uploaded_macro_code.end());
|
||||
const auto rebased_method = method - *mid_method;
|
||||
std::vector<u32> rebased_code(source->second.begin() + rebased_method,
|
||||
source->second.end());
|
||||
const auto [it, inserted] = uploaded_macro_code.emplace(method, std::move(rebased_code));
|
||||
ASSERT(inserted);
|
||||
code = it->second;
|
||||
} else {
|
||||
code = macro_code->second;
|
||||
}
|
||||
|
||||
auto& ci = macro_cache[method];
|
||||
ci.hash = Common::HashRange(code.begin(), code.end());
|
||||
if (!Settings::values.disable_macro_hle) {
|
||||
ci.program = GetHLEProgram(ci.hash);
|
||||
}
|
||||
if (std::holds_alternative<std::monostate>(ci.program)) {
|
||||
ci.program = Compile(system, maxwell3d, code);
|
||||
}
|
||||
|
||||
execute_variant(ci.program);
|
||||
if (Settings::values.dump_macros) {
|
||||
Dump(ci.hash, code, !std::holds_alternative<std::monostate>(ci.program));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user