mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-16 13:22:41 +00:00
[core, gpu, threads] Multithreading refactor (#4254)
This insufferable work tries to cover some holes on previous threading implementation from yuzu's team, starting with Windows and Linux reordering of priorities (NICE), reworks previous Android's threading and cpu affinity with adpf, adjust emulated clocks/gpu for better "accuracy" with their work, bumps android minSDK for all flavors, legacy will now work with AP 29 to cover A10 - A12, standard will reach A13 as base and finally the optimized build will come with API 35, mostly targeted on devices with A15 support and newer, NDK and AGP wasn't upgraded yet. The performance cost efficiency have been improved based on device power configuration; preventing overheating if certain devices tended to fall into NICE0 (not allocated threads priority, all task ran with higher priority, 11 tasks running within the limited 2 - 7 threads available on the most common configuration 1x3x4 or 1x4x3). Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4254
This commit is contained in:
+58
-30
@@ -10,6 +10,7 @@
|
||||
#include <condition_variable>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/settings.h"
|
||||
@@ -39,6 +40,19 @@
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
namespace {
|
||||
constexpr u64 GpuClockMultiplier(Settings::GpuClock clock) {
|
||||
switch (clock) {
|
||||
case Settings::GpuClock::Boost:
|
||||
return 256;
|
||||
case Settings::GpuClock::Overclock:
|
||||
return 512;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
struct GPU::Impl {
|
||||
explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_)
|
||||
: system{system_}
|
||||
@@ -116,7 +130,7 @@ struct GPU::Impl {
|
||||
[[nodiscard]] u64 RequestSyncOperation(Func&& action) {
|
||||
std::unique_lock lck{sync_request_mutex};
|
||||
const u64 fence = ++last_sync_fence;
|
||||
sync_requests.emplace_back(action);
|
||||
sync_requests.emplace_back(std::forward<Func>(action));
|
||||
return fence;
|
||||
}
|
||||
|
||||
@@ -145,14 +159,8 @@ struct GPU::Impl {
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 GetTicks() const {
|
||||
u64 gpu_tick = system.CoreTiming().GetGPUTicks();
|
||||
Settings::GpuOverclock overclock = Settings::values.fast_gpu_time.GetValue();
|
||||
|
||||
if (overclock != Settings::GpuOverclock::Normal) {
|
||||
gpu_tick /= 256 * u64(overclock);
|
||||
}
|
||||
|
||||
return gpu_tick;
|
||||
const u64 gpu_tick = system.CoreTiming().GetGPUTicks();
|
||||
return gpu_tick / GpuClockMultiplier(Settings::values.gpu_clock.GetValue());
|
||||
}
|
||||
|
||||
void RendererFrameEndNotify() {
|
||||
@@ -225,9 +233,9 @@ struct GPU::Impl {
|
||||
}
|
||||
|
||||
void RequestComposite(std::vector<Tegra::FramebufferConfig>&& layers, std::vector<Service::Nvidia::NvFence>&& fences) {
|
||||
size_t num_fences{fences.size()};
|
||||
const size_t num_fences{fences.size()};
|
||||
size_t current_request_counter{};
|
||||
{
|
||||
if (num_fences != 0) {
|
||||
std::unique_lock<std::mutex> lk(request_swap_mutex);
|
||||
if (free_swap_counters.empty()) {
|
||||
current_request_counter = request_swap_counters.size();
|
||||
@@ -238,27 +246,42 @@ struct GPU::Impl {
|
||||
free_swap_counters.pop_front();
|
||||
}
|
||||
}
|
||||
const auto wait_fence = RequestSyncOperation([this, current_request_counter, &layers, &fences, num_fences] {
|
||||
auto& syncpoint_manager = system.Host1x().GetSyncpointManager();
|
||||
if (num_fences == 0) {
|
||||
renderer->Composite(layers);
|
||||
}
|
||||
const auto executer = [this, current_request_counter, layers_copy = layers]() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(request_swap_mutex);
|
||||
if (--request_swap_counters[current_request_counter] != 0) {
|
||||
return;
|
||||
}
|
||||
free_swap_counters.push_back(current_request_counter);
|
||||
pending_composite_fence = RequestSyncOperation(
|
||||
[this, current_request_counter, num_fences, composite_layers = std::move(layers),
|
||||
composite_fences = std::move(fences)] {
|
||||
if (num_fences == 0) {
|
||||
renderer->Composite(composite_layers);
|
||||
return;
|
||||
}
|
||||
renderer->Composite(layers_copy);
|
||||
};
|
||||
for (size_t i = 0; i < num_fences; i++) {
|
||||
syncpoint_manager.RegisterGuestAction(fences[i].id, fences[i].value, executer);
|
||||
}
|
||||
});
|
||||
auto& syncpoint_manager = system.Host1x().GetSyncpointManager();
|
||||
const auto executer = [this, current_request_counter, composite_layers]() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(request_swap_mutex);
|
||||
if (--request_swap_counters[current_request_counter] != 0) {
|
||||
return;
|
||||
}
|
||||
free_swap_counters.push_back(current_request_counter);
|
||||
}
|
||||
renderer->Composite(composite_layers);
|
||||
};
|
||||
for (size_t i = 0; i < num_fences; i++) {
|
||||
syncpoint_manager.RegisterGuestAction(composite_fences[i].id,
|
||||
composite_fences[i].value, executer);
|
||||
}
|
||||
});
|
||||
gpu_thread.TickGPU(is_async);
|
||||
WaitForSyncOperation(wait_fence);
|
||||
}
|
||||
|
||||
void WaitForComposite() {
|
||||
const u64 fence = pending_composite_fence;
|
||||
if (fence == 0) {
|
||||
return;
|
||||
}
|
||||
pending_composite_fence = 0;
|
||||
if (shutting_down.load(std::memory_order_relaxed)) {
|
||||
return;
|
||||
}
|
||||
WaitForSyncOperation(fence);
|
||||
}
|
||||
|
||||
std::vector<u8> GetAppletCaptureBuffer() {
|
||||
@@ -311,6 +334,7 @@ struct GPU::Impl {
|
||||
std::deque<size_t> free_swap_counters;
|
||||
std::deque<size_t> request_swap_counters;
|
||||
std::mutex request_swap_mutex;
|
||||
u64 pending_composite_fence{};
|
||||
};
|
||||
|
||||
GPU::GPU(Core::System& system, bool is_async, bool use_nvdec)
|
||||
@@ -428,6 +452,10 @@ void GPU::RequestComposite(std::vector<Tegra::FramebufferConfig>&& layers,
|
||||
impl->RequestComposite(std::move(layers), std::move(fences));
|
||||
}
|
||||
|
||||
void GPU::WaitForComposite() {
|
||||
impl->WaitForComposite();
|
||||
}
|
||||
|
||||
std::vector<u8> GPU::GetAppletCaptureBuffer() {
|
||||
return impl->GetAppletCaptureBuffer();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user