mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-24 16:30:44 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ade32609df | |||
| 8f64430215 |
@@ -65,6 +65,17 @@ static inline u64 xgetbv(u32 index) {
|
||||
|
||||
namespace Common {
|
||||
|
||||
CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
|
||||
if (brand_string == "GenuineIntel") {
|
||||
return Manufacturer::Intel;
|
||||
} else if (brand_string == "AuthenticAMD") {
|
||||
return Manufacturer::AMD;
|
||||
} else if (brand_string == "HygonGenuine") {
|
||||
return Manufacturer::Hygon;
|
||||
}
|
||||
return Manufacturer::Unknown;
|
||||
}
|
||||
|
||||
// Detects the various CPU features
|
||||
static CPUCaps Detect() {
|
||||
CPUCaps caps = {};
|
||||
@@ -83,6 +94,8 @@ static CPUCaps Detect() {
|
||||
std::memcpy(&caps.brand_string[4], &cpu_id[3], sizeof(u32));
|
||||
std::memcpy(&caps.brand_string[8], &cpu_id[2], sizeof(u32));
|
||||
|
||||
caps.manufacturer = CPUCaps::ParseManufacturer(caps.brand_string);
|
||||
|
||||
// Set reasonable default cpu string even if brand string not available
|
||||
std::strncpy(caps.cpu_string, caps.brand_string, std::size(caps.brand_string));
|
||||
|
||||
@@ -121,21 +134,14 @@ static CPUCaps Detect() {
|
||||
__cpuidex(cpu_id, 0x00000007, 0x00000000);
|
||||
// Can't enable AVX{2,512} unless the XSAVE/XGETBV checks above passed
|
||||
if (caps.avx) {
|
||||
// ebx
|
||||
caps.avx2 = Common::Bit<5>(cpu_id[1]);
|
||||
caps.avx512f = Common::Bit<16>(cpu_id[1]);
|
||||
caps.avx512dq = Common::Bit<17>(cpu_id[1]);
|
||||
caps.avx512cd = Common::Bit<28>(cpu_id[1]);
|
||||
caps.avx512bw = Common::Bit<30>(cpu_id[1]);
|
||||
caps.avx512vl = Common::Bit<31>(cpu_id[1]);
|
||||
// ecx
|
||||
caps.avx512vbmi = Common::Bit<1>(cpu_id[2]);
|
||||
caps.avx512vbmi2 = Common::Bit<6>(cpu_id[2]);
|
||||
caps.avx512vnni = Common::Bit<11>(cpu_id[2]);
|
||||
caps.avx512bitalg = Common::Bit<12>(cpu_id[2]);
|
||||
caps.avx512popcntq = Common::Bit<14>(cpu_id[2]);
|
||||
// edx
|
||||
caps.avx512bf16 = Common::Bit<7>(cpu_id[3]);
|
||||
}
|
||||
|
||||
caps.bmi1 = Common::Bit<3>(cpu_id[1]);
|
||||
@@ -215,15 +221,17 @@ std::optional<int> GetProcessorCount() {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
|
||||
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||
// Now query the core count.
|
||||
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
return int(std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
||||
return proc_info.Relationship == RelationProcessorCore;
|
||||
}));
|
||||
return static_cast<int>(
|
||||
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
||||
return proc_info.Relationship == RelationProcessorCore;
|
||||
}));
|
||||
#elif defined(__unix__)
|
||||
const int thread_count = std::thread::hardware_concurrency();
|
||||
std::ifstream smt("/sys/devices/system/cpu/smt/active");
|
||||
|
||||
+48
-44
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
@@ -15,6 +12,17 @@ namespace Common {
|
||||
|
||||
/// x86/x64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
|
||||
enum class Manufacturer : u8 {
|
||||
Unknown = 0,
|
||||
Intel = 1,
|
||||
AMD = 2,
|
||||
Hygon = 3,
|
||||
};
|
||||
|
||||
static Manufacturer ParseManufacturer(std::string_view brand_string);
|
||||
|
||||
Manufacturer manufacturer;
|
||||
char brand_string[13];
|
||||
|
||||
char cpu_string[48];
|
||||
@@ -28,49 +36,45 @@ struct CPUCaps {
|
||||
u32 crystal_frequency;
|
||||
u64 tsc_frequency; // Derived from the above three values
|
||||
|
||||
#define CPU_CAPS_LIST \
|
||||
CPU_CAPS_ELEM(sse) \
|
||||
CPU_CAPS_ELEM(sse2) \
|
||||
CPU_CAPS_ELEM(sse3) \
|
||||
CPU_CAPS_ELEM(ssse3) \
|
||||
CPU_CAPS_ELEM(sse4_1) \
|
||||
CPU_CAPS_ELEM(sse4_2) \
|
||||
CPU_CAPS_ELEM(avx) \
|
||||
CPU_CAPS_ELEM(avx_vnni) \
|
||||
CPU_CAPS_ELEM(avx2) \
|
||||
CPU_CAPS_ELEM(avx512f) \
|
||||
CPU_CAPS_ELEM(avx512dq) \
|
||||
CPU_CAPS_ELEM(avx512cd) \
|
||||
CPU_CAPS_ELEM(avx512bw) \
|
||||
CPU_CAPS_ELEM(avx512vl) \
|
||||
CPU_CAPS_ELEM(avx512vbmi) \
|
||||
CPU_CAPS_ELEM(avx512vbmi2) \
|
||||
CPU_CAPS_ELEM(avx512vnni) \
|
||||
CPU_CAPS_ELEM(avx512bitalg) \
|
||||
CPU_CAPS_ELEM(avx512popcntq) \
|
||||
CPU_CAPS_ELEM(avx512bf16) \
|
||||
CPU_CAPS_ELEM(aes) \
|
||||
CPU_CAPS_ELEM(bmi1) \
|
||||
CPU_CAPS_ELEM(bmi2) \
|
||||
CPU_CAPS_ELEM(f16c) \
|
||||
CPU_CAPS_ELEM(fma) \
|
||||
CPU_CAPS_ELEM(fma4) \
|
||||
CPU_CAPS_ELEM(gfni) \
|
||||
CPU_CAPS_ELEM(invariant_tsc) \
|
||||
CPU_CAPS_ELEM(lzcnt) \
|
||||
CPU_CAPS_ELEM(monitorx) \
|
||||
CPU_CAPS_ELEM(movbe) \
|
||||
CPU_CAPS_ELEM(pclmulqdq) \
|
||||
CPU_CAPS_ELEM(popcnt) \
|
||||
CPU_CAPS_ELEM(sha) \
|
||||
CPU_CAPS_ELEM(waitpkg)
|
||||
#define CPU_CAPS_ELEM(n) bool n : 1;
|
||||
CPU_CAPS_LIST
|
||||
#undef CPU_CAPS_ELEM
|
||||
bool sse : 1;
|
||||
bool sse2 : 1;
|
||||
bool sse3 : 1;
|
||||
bool ssse3 : 1;
|
||||
bool sse4_1 : 1;
|
||||
bool sse4_2 : 1;
|
||||
|
||||
bool avx : 1;
|
||||
bool avx_vnni : 1;
|
||||
bool avx2 : 1;
|
||||
bool avx512f : 1;
|
||||
bool avx512dq : 1;
|
||||
bool avx512cd : 1;
|
||||
bool avx512bw : 1;
|
||||
bool avx512vl : 1;
|
||||
bool avx512vbmi : 1;
|
||||
bool avx512bitalg : 1;
|
||||
|
||||
bool aes : 1;
|
||||
bool bmi1 : 1;
|
||||
bool bmi2 : 1;
|
||||
bool f16c : 1;
|
||||
bool fma : 1;
|
||||
bool fma4 : 1;
|
||||
bool gfni : 1;
|
||||
bool invariant_tsc : 1;
|
||||
bool lzcnt : 1;
|
||||
bool monitorx : 1;
|
||||
bool movbe : 1;
|
||||
bool pclmulqdq : 1;
|
||||
bool popcnt : 1;
|
||||
bool sha : 1;
|
||||
bool waitpkg : 1;
|
||||
};
|
||||
|
||||
/// Gets the supported capabilities of the host CPU
|
||||
/// @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
||||
/**
|
||||
* Gets the supported capabilities of the host CPU
|
||||
* @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
||||
*/
|
||||
const CPUCaps& GetCPUCaps();
|
||||
|
||||
/// Detects CPU core count
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -15,53 +18,37 @@ public:
|
||||
InvalidationAccumulator() = default;
|
||||
~InvalidationAccumulator() = default;
|
||||
|
||||
void Add(GPUVAddr address, size_t size) {
|
||||
const auto reset_values = [&]() {
|
||||
if (has_collected) {
|
||||
void Add(GPUVAddr address, size_t size) noexcept {
|
||||
auto const end_address = start_address + accumulated_size;
|
||||
if (!(address >= start_address && address + size <= end_address)) {
|
||||
size = ((address + size + atomicity_size_mask) & atomicity_mask) - address;
|
||||
address = address & atomicity_mask;
|
||||
if (start_address == 0) {
|
||||
start_address = address;
|
||||
accumulated_size = size;
|
||||
// will now have collected as this point
|
||||
} else if (address != end_address) {
|
||||
buffer.emplace_back(start_address, accumulated_size);
|
||||
start_address = address;
|
||||
accumulated_size = size;
|
||||
} else {
|
||||
accumulated_size += size;
|
||||
}
|
||||
start_address = address;
|
||||
accumulated_size = size;
|
||||
last_collection = start_address + size;
|
||||
};
|
||||
if (address >= start_address && address + size <= last_collection) [[likely]] {
|
||||
return;
|
||||
}
|
||||
size = ((address + size + atomicity_size_mask) & atomicity_mask) - address;
|
||||
address = address & atomicity_mask;
|
||||
if (!has_collected) [[unlikely]] {
|
||||
reset_values();
|
||||
has_collected = true;
|
||||
return;
|
||||
}
|
||||
if (address != last_collection) [[unlikely]] {
|
||||
reset_values();
|
||||
return;
|
||||
}
|
||||
accumulated_size += size;
|
||||
last_collection += size;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
buffer.clear();
|
||||
start_address = 0;
|
||||
last_collection = 0;
|
||||
has_collected = false;
|
||||
}
|
||||
|
||||
bool AnyAccumulated() const {
|
||||
return has_collected;
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void Callback(Func&& func) {
|
||||
if (!has_collected) {
|
||||
return;
|
||||
}
|
||||
buffer.emplace_back(start_address, accumulated_size);
|
||||
for (auto& [address, size] : buffer) {
|
||||
func(address, size);
|
||||
template <typename F>
|
||||
[[nodiscard]] bool InvalidateAll(F&& f) noexcept {
|
||||
if (start_address > 0) {
|
||||
for (auto [address, size] : buffer)
|
||||
f(address, size);
|
||||
f(start_address, accumulated_size);
|
||||
buffer.clear();
|
||||
start_address = 0;
|
||||
accumulated_size = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -69,11 +56,9 @@ private:
|
||||
static constexpr size_t atomicity_size = 1ULL << atomicity_bits;
|
||||
static constexpr size_t atomicity_size_mask = atomicity_size - 1;
|
||||
static constexpr size_t atomicity_mask = ~atomicity_size_mask;
|
||||
GPUVAddr start_address{};
|
||||
GPUVAddr last_collection{};
|
||||
size_t accumulated_size{};
|
||||
bool has_collected{};
|
||||
std::vector<std::pair<VAddr, size_t>> buffer;
|
||||
GPUVAddr start_address = 0;
|
||||
size_t accumulated_size = 0;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
||||
@@ -26,16 +26,14 @@ using Tegra::Memory::GuestMemoryFlags;
|
||||
|
||||
std::atomic<size_t> MemoryManager::unique_identifier_generator{};
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
|
||||
u64 address_space_bits_, GPUVAddr split_address_, u64 big_page_bits_,
|
||||
u64 page_bits_)
|
||||
: system{system_}, memory{memory_}, address_space_bits{address_space_bits_},
|
||||
split_address{split_address_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
|
||||
entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
|
||||
page_bits != big_page_bits ? page_bits : 0},
|
||||
kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add(
|
||||
1, std::memory_order_acq_rel)},
|
||||
accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} {
|
||||
MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_, u64 address_space_bits_, GPUVAddr split_address_, u64 big_page_bits_, u64 page_bits_)
|
||||
: system{system_}, memory{memory_}, address_space_bits{address_space_bits_}
|
||||
, split_address{split_address_}, page_bits{page_bits_}, big_page_bits{big_page_bits_}
|
||||
, entries{}, big_entries{}
|
||||
, page_table{address_space_bits, address_space_bits + page_bits - 38, page_bits != big_page_bits ? page_bits : 0}
|
||||
, kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add(1, std::memory_order_acq_rel)}
|
||||
, accumulator{}
|
||||
{
|
||||
address_space_size = 1ULL << address_space_bits;
|
||||
page_size = 1ULL << page_bits;
|
||||
page_mask = page_size - 1ULL;
|
||||
@@ -54,10 +52,9 @@ MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager&
|
||||
entries.resize(page_table_size / 32, 0);
|
||||
}
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_,
|
||||
GPUVAddr split_address_, u64 big_page_bits_, u64 page_bits_)
|
||||
: MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, split_address_,
|
||||
big_page_bits_, page_bits_) {}
|
||||
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, GPUVAddr split_address_, u64 big_page_bits_, u64 page_bits_)
|
||||
: MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, split_address_, big_page_bits_, page_bits_)
|
||||
{}
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
@@ -469,10 +466,9 @@ void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buf
|
||||
WriteBlockImpl<false>(gpu_dest_addr, src_buffer, size, VideoCommon::CacheType::None);
|
||||
}
|
||||
|
||||
void MemoryManager::WriteBlockCached(GPUVAddr gpu_dest_addr, const void* src_buffer,
|
||||
std::size_t size) {
|
||||
void MemoryManager::WriteBlockCached(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size) {
|
||||
WriteBlockImpl<false>(gpu_dest_addr, src_buffer, size, VideoCommon::CacheType::None);
|
||||
accumulator->Add(gpu_dest_addr, size);
|
||||
accumulator.Add(gpu_dest_addr, size);
|
||||
}
|
||||
|
||||
void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size,
|
||||
@@ -756,15 +752,13 @@ void MemoryManager::GetSubmappedRangeImpl(
|
||||
}
|
||||
|
||||
void MemoryManager::FlushCaching() {
|
||||
if (!accumulator->AnyAccumulated()) {
|
||||
return;
|
||||
}
|
||||
accumulator->Callback([this](GPUVAddr addr, size_t size) {
|
||||
// Flush from the invalidate accumulator
|
||||
if (accumulator.InvalidateAll([this](GPUVAddr addr, size_t size) {
|
||||
GetSubmappedRangeImpl<false>(addr, size, page_stash2);
|
||||
});
|
||||
rasterizer->InnerInvalidation(VideoCommon::FixSmallVectorADL(page_stash2));
|
||||
page_stash2.clear();
|
||||
accumulator->Clear();
|
||||
})) {
|
||||
rasterizer->InnerInvalidation(VideoCommon::FixSmallVectorADL(page_stash2));
|
||||
page_stash2.clear();
|
||||
}
|
||||
}
|
||||
|
||||
const u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) const {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "common/range_map.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "common/virtual_buffer.h"
|
||||
#include "video_core/invalidation_accumulator.h"
|
||||
#include "video_core/cache_types.h"
|
||||
#include "video_core/host1x/gpu_device_memory_manager.h"
|
||||
#include "video_core/pte_kind.h"
|
||||
@@ -26,10 +27,6 @@ namespace VideoCore {
|
||||
class RasterizerInterface;
|
||||
}
|
||||
|
||||
namespace VideoCommon {
|
||||
class InvalidationAccumulator;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
} // namespace Core
|
||||
@@ -249,7 +246,7 @@ private:
|
||||
static constexpr size_t continuous_bits = 64;
|
||||
|
||||
const size_t unique_identifier;
|
||||
std::unique_ptr<VideoCommon::InvalidationAccumulator> accumulator;
|
||||
VideoCommon::InvalidationAccumulator accumulator;
|
||||
|
||||
static std::atomic<size_t> unique_identifier_generator;
|
||||
|
||||
|
||||
+36
-18
@@ -488,31 +488,49 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||
QtCommon::system->HIDCore().ReloadInputDevices();
|
||||
controller_dialog->refreshConfiguration();
|
||||
|
||||
const auto yuzu_build = fmt::format("Eden | {}-{}", Common::g_scm_branch, Common::g_scm_desc);
|
||||
const auto override_build = fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), Common::g_build_id);
|
||||
const auto branch_name = std::string(Common::g_scm_branch);
|
||||
const auto description = std::string(Common::g_scm_desc);
|
||||
const auto build_id = std::string(Common::g_build_id);
|
||||
|
||||
const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description);
|
||||
const auto override_build =
|
||||
fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id);
|
||||
const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build;
|
||||
const auto processor_count = std::thread::hardware_concurrency();
|
||||
|
||||
LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version);
|
||||
LogRuntimes();
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
auto const& caps = Common::GetCPUCaps();
|
||||
std::string ext_string{};
|
||||
#define CPU_CAPS_ELEM(n) if (caps.n) ext_string += " | " #n;
|
||||
CPU_CAPS_LIST
|
||||
#undef CPU_CAPS_ELEM
|
||||
if (auto const processor_core = Common::GetProcessorCount()) {
|
||||
LOG_INFO(Frontend, "Host CPU: {} ({} cores, {} threads) {}", caps.cpu_string, *processor_core, processor_count, ext_string);
|
||||
} else {
|
||||
LOG_INFO(Frontend, "Host CPU: {} ({} threads) {}", caps.cpu_string, processor_count, ext_string);
|
||||
const auto& caps = Common::GetCPUCaps();
|
||||
std::string cpu_string = caps.cpu_string;
|
||||
if (caps.avx || caps.avx2 || caps.avx512f) {
|
||||
cpu_string += " | AVX";
|
||||
if (caps.avx512f) {
|
||||
cpu_string += "512";
|
||||
} else if (caps.avx2) {
|
||||
cpu_string += '2';
|
||||
}
|
||||
if (caps.fma || caps.fma4) {
|
||||
cpu_string += " | FMA";
|
||||
}
|
||||
}
|
||||
LOG_INFO(Frontend, "Host CPU: {}", cpu_string);
|
||||
if (std::optional<int> processor_core = Common::GetProcessorCount()) {
|
||||
LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core);
|
||||
}
|
||||
#endif
|
||||
LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count);
|
||||
LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString());
|
||||
LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
||||
LOG_INFO(Frontend, "Host RAM: {:.2f} GiB",
|
||||
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
||||
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
|
||||
#ifdef _WIN32
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count());
|
||||
QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms",
|
||||
std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
|
||||
Common::Windows::SetCurrentTimerResolutionToMaximum())
|
||||
.count());
|
||||
QtCommon::system->CoreTiming().SetTimerResolutionNs(
|
||||
Common::Windows::GetCurrentTimerResolution());
|
||||
#endif
|
||||
UpdateWindowTitle();
|
||||
|
||||
@@ -520,10 +538,10 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
||||
|
||||
#ifdef ENABLE_UPDATE_CHECKER
|
||||
if (UISettings::values.check_for_updates) {
|
||||
update_future = QtConcurrent::run([] -> std::optional<UpdateChecker::Update> {
|
||||
return UpdateChecker::GetUpdate();
|
||||
});
|
||||
update_watcher.connect(&update_watcher, &QFutureWatcher<QString>::finished, this, &MainWindow::OnEmulatorUpdateAvailable);
|
||||
update_future = QtConcurrent::run(
|
||||
[]() -> std::optional<UpdateChecker::Update> { return UpdateChecker::GetUpdate(); });
|
||||
update_watcher.connect(&update_watcher, &QFutureWatcher<QString>::finished, this,
|
||||
&MainWindow::OnEmulatorUpdateAvailable);
|
||||
update_watcher.setFuture(update_future);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user