diff --git a/src/video_core/macro.cpp b/src/video_core/macro.cpp index 491105a1ec..3d7ac04851 100644 --- a/src/video_core/macro.cpp +++ b/src/video_core/macro.cpp @@ -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 params, u32 method) { Reset(); @@ -1345,80 +1337,92 @@ static void Dump(u64 hash, std::span code, bool decompiled = false) { macro_file.write(reinterpret_cast(code.data()), code.size_bytes()); } -void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters) { - auto const execute_variant = [&system, &maxwell3d, ¶meters, method](AnyCachedMacro& acm) { - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if(&acm)) - return a->Execute(system, maxwell3d, parameters, method); - if (auto a = std::get_if>(&acm)) - return a->get()->Execute(system, maxwell3d, parameters, method); +void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, + std::span parameters) { + const auto execute_variant = [&system, &maxwell3d, ¶meters, + method](AnyCachedMacro& cached) { + if (std::holds_alternative(cached) || + std::holds_alternative>(cached) || + Settings::values.disable_macro_hle) { + maxwell3d.RefreshParameters(); + } + + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if(&cached)) + return program->Execute(system, maxwell3d, parameters, method); + if (auto program = std::get_if>(&cached)) + return program->get()->Execute(system, maxwell3d, parameters, method); + + UNREACHABLE(); }; 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 + execute_variant(it->second.program); + return; + } + + // Macro not compiled, check if it's uploaded and if so, compile it + std::span code; + auto macro_code = uploaded_macro_code.find(method); + if (macro_code == uploaded_macro_code.end()) { std::optional 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; + 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; } } - 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 { - maxwell3d.RefreshParameters(); - } - execute_variant(ci.program); - if (Settings::values.dump_macros) { - Dump(ci.hash, macro_code->second, !std::holds_alternative(ci.program)); + 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 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(ci.program)) { + ci.program = Compile(system, maxwell3d, code); + } + + execute_variant(ci.program); + if (Settings::values.dump_macros) { + Dump(ci.hash, code, !std::holds_alternative(ci.program)); } }