mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-07 20:50:58 +00:00
[TEST] Rework Android CPU affinity/ threading 2
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
@@ -111,6 +112,35 @@ const cpu_set_t& PerformanceCoreMask() {
|
|||||||
static const cpu_set_t mask = ComputePerformanceCoreMask();
|
static const cpu_set_t mask = ComputePerformanceCoreMask();
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_set_t ComputeEfficiencyCoreMask() {
|
||||||
|
cpu_set_t mask;
|
||||||
|
CPU_ZERO(&mask);
|
||||||
|
|
||||||
|
const cpu_set_t& performance = PerformanceCoreMask();
|
||||||
|
if (CPU_COUNT(&performance) == 0) {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_set_t allowed;
|
||||||
|
CPU_ZERO(&allowed);
|
||||||
|
if (sched_getaffinity(gettid(), sizeof(allowed), &allowed) != 0) {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int total = static_cast<int>(std::thread::hardware_concurrency());
|
||||||
|
for (int cpu = 0; cpu < total; ++cpu) {
|
||||||
|
if (CPU_ISSET(cpu, &allowed) && !CPU_ISSET(cpu, &performance)) {
|
||||||
|
CPU_SET(cpu, &mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cpu_set_t& EfficiencyCoreMask() {
|
||||||
|
static const cpu_set_t mask = ComputeEfficiencyCoreMask();
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -234,6 +264,18 @@ void SetCurrentThreadToPerformanceCores() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetCurrentThreadToEfficiencyCores() {
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
const cpu_set_t& mask = EfficiencyCoreMask();
|
||||||
|
if (CPU_COUNT(&mask) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sched_setaffinity(gettid(), sizeof(mask), &mask) != 0) {
|
||||||
|
LOG_DEBUG(Common, "Could not restrict thread to efficiency cores: {}", GetLastErrorMsg());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
// On Linux and UNIX systems, a futex would nominally be used to cover the costs
|
// On Linux and UNIX systems, a futex would nominally be used to cover the costs
|
||||||
// the idea is that it's intuitivelly cheaper to use a direct instruction as opposed to a full futex call
|
// the idea is that it's intuitivelly cheaper to use a direct instruction as opposed to a full futex call
|
||||||
|
|||||||
@@ -99,8 +99,14 @@ enum class ThreadPriority : u32 {
|
|||||||
Critical = 4,
|
Critical = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ThreadPlacement : u32 {
|
||||||
|
Default = 0,
|
||||||
|
Background = 1,
|
||||||
|
};
|
||||||
|
|
||||||
void SetCurrentThreadPriority(ThreadPriority new_priority);
|
void SetCurrentThreadPriority(ThreadPriority new_priority);
|
||||||
void SetCurrentThreadName(const char* name);
|
void SetCurrentThreadName(const char* name);
|
||||||
void SetCurrentThreadToPerformanceCores();
|
void SetCurrentThreadToPerformanceCores();
|
||||||
|
void SetCurrentThreadToEfficiencyCores();
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
@@ -37,10 +37,15 @@ class StatefulThreadWorker {
|
|||||||
using StateMaker = std::conditional_t<with_state, std::function<StateType()>, DummyCallable>;
|
using StateMaker = std::conditional_t<with_state, std::function<StateType()>, DummyCallable>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StatefulThreadWorker(size_t num_workers, std::string name, StateMaker func = {})
|
explicit StatefulThreadWorker(size_t num_workers, std::string name, StateMaker func = {},
|
||||||
|
ThreadPlacement placement = ThreadPlacement::Default)
|
||||||
: workers_queued{num_workers}, thread_name{std::move(name)} {
|
: workers_queued{num_workers}, thread_name{std::move(name)} {
|
||||||
const auto lambda = [this, func](std::stop_token stop_token) {
|
const auto lambda = [this, func, placement](std::stop_token stop_token) {
|
||||||
Common::SetCurrentThreadName(thread_name.c_str());
|
Common::SetCurrentThreadName(thread_name.c_str());
|
||||||
|
if (placement == ThreadPlacement::Background) {
|
||||||
|
Common::SetCurrentThreadPriority(ThreadPriority::Low);
|
||||||
|
Common::SetCurrentThreadToEfficiencyCores();
|
||||||
|
}
|
||||||
{
|
{
|
||||||
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func()};
|
[[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func()};
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
|
|||||||
@@ -349,8 +349,9 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()},
|
use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()},
|
||||||
use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()},
|
use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()},
|
||||||
workers(device.HasBrokenParallelShaderCompiling() ? 1ULL : GetTotalPipelineWorkers(),
|
workers(device.HasBrokenParallelShaderCompiling() ? 1ULL : GetTotalPipelineWorkers(),
|
||||||
"VkPipelineBuilder"),
|
"VkPipelineBuilder", {}, Common::ThreadPlacement::Background),
|
||||||
serialization_thread(1, "VkPipelineSerialization") {
|
serialization_thread(1, "VkPipelineSerialization", {},
|
||||||
|
Common::ThreadPlacement::Background) {
|
||||||
const auto& float_control{device.FloatControlProperties()};
|
const auto& float_control{device.FloatControlProperties()};
|
||||||
const VkDriverId driver_id{device.GetDriverID()};
|
const VkDriverId driver_id{device.GetDriverID()};
|
||||||
const VkShaderStageFlags subgroup_stages{device.GetSubgroupSupportedStages()};
|
const VkShaderStageFlags subgroup_stages{device.GetSubgroupSupportedStages()};
|
||||||
|
|||||||
@@ -529,7 +529,8 @@ private:
|
|||||||
u64 frame_tick = 0;
|
u64 frame_tick = 0;
|
||||||
u64 last_sampler_gc_frame = (std::numeric_limits<u64>::max)();
|
u64 last_sampler_gc_frame = (std::numeric_limits<u64>::max)();
|
||||||
|
|
||||||
Common::ThreadWorker texture_decode_worker{1, "TextureDecoder"};
|
Common::ThreadWorker texture_decode_worker{1, "TextureDecoder", {},
|
||||||
|
Common::ThreadPlacement::Background};
|
||||||
std::vector<std::unique_ptr<AsyncDecodeContext>> async_decodes;
|
std::vector<std::unique_ptr<AsyncDecodeContext>> async_decodes;
|
||||||
|
|
||||||
std::deque<PendingUnswizzle> unswizzle_queue;
|
std::deque<PendingUnswizzle> unswizzle_queue;
|
||||||
|
|||||||
@@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -10,7 +10,8 @@ namespace Tegra::Texture {
|
|||||||
|
|
||||||
Common::ThreadWorker& GetThreadWorkers() {
|
Common::ThreadWorker& GetThreadWorkers() {
|
||||||
static Common::ThreadWorker workers{(std::max)(std::thread::hardware_concurrency(), 2U) / 2,
|
static Common::ThreadWorker workers{(std::max)(std::thread::hardware_concurrency(), 2U) / 2,
|
||||||
"ImageTranscode"};
|
"ImageTranscode", {},
|
||||||
|
Common::ThreadPlacement::Background};
|
||||||
|
|
||||||
return workers;
|
return workers;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user