From 28b2a7a8a1a4079ec086a1abb30c3e319519ace0 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Wed, 28 Dec 2022 20:36:52 +0000 Subject: [PATCH] Dynamically apply GPU turbo clocks only when GPU submissions are queued Allows for the GPU to clock down in cases where it's idle for most of the time, while still forcing maximum clocks when we care. --- .../cpp/skyline/common/android_settings.h | 1 + app/src/main/cpp/skyline/common/settings.h | 1 + .../gpu/interconnect/command_executor.cpp | 26 ++++++++++++++++--- .../gpu/interconnect/command_executor.h | 3 ++- .../java/emu/skyline/EmulationActivity.kt | 5 ---- .../java/emu/skyline/utils/NativeSettings.kt | 1 + 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/src/main/cpp/skyline/common/android_settings.h b/app/src/main/cpp/skyline/common/android_settings.h index 1c27f543..ca7e7553 100644 --- a/app/src/main/cpp/skyline/common/android_settings.h +++ b/app/src/main/cpp/skyline/common/android_settings.h @@ -43,6 +43,7 @@ namespace skyline { executorSlotCountScale = ktSettings.GetInt("executorSlotCountScale"); executorFlushThreshold = ktSettings.GetInt("executorFlushThreshold"); useDirectMemoryImport = ktSettings.GetBool("useDirectMemoryImport"); + forceMaxGpuClocks = ktSettings.GetBool("forceMaxGpuClocks"); enableFastGpuReadbackHack = ktSettings.GetBool("enableFastGpuReadbackHack"); isAudioOutputDisabled = ktSettings.GetBool("isAudioOutputDisabled"); validationLayer = ktSettings.GetBool("validationLayer"); diff --git a/app/src/main/cpp/skyline/common/settings.h b/app/src/main/cpp/skyline/common/settings.h index cee2c07a..9079c71d 100644 --- a/app/src/main/cpp/skyline/common/settings.h +++ b/app/src/main/cpp/skyline/common/settings.h @@ -75,6 +75,7 @@ namespace skyline { Setting executorSlotCountScale; //!< Number of GPU executor slots that can be used concurrently Setting executorFlushThreshold; //!< Number of commands that need to accumulate before they're flushed to the GPU Setting useDirectMemoryImport; //!< If buffer emulation should be done by importing guest buffer mappings + Setting forceMaxGpuClocks; //!< If the GPU should be forced to run at maximum clocks // Hacks Setting enableFastGpuReadbackHack; //!< If the CPU texture readback skipping hack should be used diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp index de510eb3..c259c634 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp @@ -2,6 +2,7 @@ // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) #include +#include #include #include #include @@ -195,13 +196,29 @@ namespace skyline::gpu::interconnect { void ExecutionWaiterThread::Run() { signal::SetSignalHandler({SIGSEGV}, nce::NCE::HostSignalHandler); // We may access NCE trapped memory + // Enable turbo clocks to begin with if requested + if (*state.settings->forceMaxGpuClocks) + adrenotools_set_turbo(true); + while (true) { std::pair, std::function> item{}; { std::unique_lock lock{mutex}; - idle = true; - condition.wait(lock, [this] { return !pendingSignalQueue.empty(); }); - idle = false; + if (pendingSignalQueue.empty()) { + idle = true; + + // Don't force turbo clocks when the GPU is idle + if (*state.settings->forceMaxGpuClocks) + adrenotools_set_turbo(false); + + condition.wait(lock, [this] { return !pendingSignalQueue.empty(); }); + + // Once we have work to do, force turbo clocks is enabled + if (*state.settings->forceMaxGpuClocks) + adrenotools_set_turbo(true); + + idle = false; + } item = std::move(pendingSignalQueue.front()); pendingSignalQueue.pop(); } @@ -216,7 +233,7 @@ namespace skyline::gpu::interconnect { } } - ExecutionWaiterThread::ExecutionWaiterThread() : thread{&ExecutionWaiterThread::Run, this} {} + ExecutionWaiterThread::ExecutionWaiterThread(const DeviceState &state) : state{state}, thread{&ExecutionWaiterThread::Run, this} {} bool ExecutionWaiterThread::IsIdle() const { return idle; @@ -232,6 +249,7 @@ namespace skyline::gpu::interconnect { : state{state}, gpu{*state.gpu}, recordThread{state}, + waiterThread{state}, tag{AllocateTag()} { RotateRecordSlot(); } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h index fbb79840..4fd4d0bd 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h @@ -97,6 +97,7 @@ namespace skyline::gpu::interconnect { */ class ExecutionWaiterThread { private: + const DeviceState &state; std::thread thread; std::mutex mutex; std::condition_variable condition; @@ -106,7 +107,7 @@ namespace skyline::gpu::interconnect { void Run(); public: - ExecutionWaiterThread(); + ExecutionWaiterThread(const DeviceState &state); bool IsIdle() const; diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index a7daacf1..a7644ba3 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -256,8 +256,6 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo force60HzRefreshRate(!preferenceSettings.maxRefreshRate) getSystemService()?.registerDisplayListener(this, null) - if (preferenceSettings.forceMaxGpuClocks) - GpuDriverHelper.forceMaxGpuClocks(true) binding.gameView.setOnTouchListener(this) @@ -291,9 +289,6 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo override fun onResume() { super.onResume() - if (preferenceSettings.forceMaxGpuClocks) - GpuDriverHelper.forceMaxGpuClocks(true) - changeAudioStatus(true) if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { diff --git a/app/src/main/java/emu/skyline/utils/NativeSettings.kt b/app/src/main/java/emu/skyline/utils/NativeSettings.kt index 2f63da16..253a2917 100644 --- a/app/src/main/java/emu/skyline/utils/NativeSettings.kt +++ b/app/src/main/java/emu/skyline/utils/NativeSettings.kt @@ -29,6 +29,7 @@ class NativeSettings(context : Context, pref : PreferenceSettings) { var executorSlotCountScale : Int = pref.executorSlotCountScale var executorFlushThreshold : Int = pref.executorFlushThreshold var useDirectMemoryImport : Boolean = pref.useDirectMemoryImport + var forceMaxGpuClocks : Boolean = pref.forceMaxGpuClocks // Hacks var enableFastGpuReadbackHack : Boolean = pref.enableFastGpuReadbackHack