diff --git a/app/src/main/cpp/driver_jni.cpp b/app/src/main/cpp/driver_jni.cpp index 8c413736..17ab9cb9 100644 --- a/app/src/main/cpp/driver_jni.cpp +++ b/app/src/main/cpp/driver_jni.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "skyline/common/signal.h" #include "skyline/common/utils.h" @@ -28,9 +29,22 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_emu_skyline_utils_GpuDriverHelper return array; } -extern "C" JNIEXPORT jboolean JNICALL Java_emu_skyline_utils_GpuDriverHelper_00024Companion_supportsCustomDriverLoading(JNIEnv *env, jobject instance) { - // Check if the Qualcomm KGSL (Kernel Graphics Support Layer) device exists, this indicates that custom drivers can be loaded +static bool CheckKgslPresent() { constexpr auto KgslPath{"/dev/kgsl-3d0"}; return access(KgslPath, F_OK) == 0; } + +extern "C" JNIEXPORT jboolean JNICALL Java_emu_skyline_utils_GpuDriverHelper_00024Companion_supportsCustomDriverLoading(JNIEnv *env, jobject instance) { + // If the KGSL device exists custom drivers can be loaded using adrenotools + return CheckKgslPresent(); +} + +extern "C" JNIEXPORT jboolean JNICALL Java_emu_skyline_utils_GpuDriverHelper_00024Companion_supportsForceMaxGpuClocks(JNIEnv *env, jobject instance) { + // If the KGSL device exists adrenotools can be used to set GPU turbo mode + return CheckKgslPresent(); +} + +extern "C" JNIEXPORT void JNICALL Java_emu_skyline_utils_GpuDriverHelper_00024Companion_forceMaxGpuClocks(JNIEnv *env, jobject instance, jboolean enable) { + adrenotools_set_turbo(enable); +} diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index 2bb3e707..a7daacf1 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -256,6 +256,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo force60HzRefreshRate(!preferenceSettings.maxRefreshRate) getSystemService()?.registerDisplayListener(this, null) + if (preferenceSettings.forceMaxGpuClocks) + GpuDriverHelper.forceMaxGpuClocks(true) binding.gameView.setOnTouchListener(this) @@ -280,12 +282,18 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo override fun onPause() { super.onPause() + if (preferenceSettings.forceMaxGpuClocks) + GpuDriverHelper.forceMaxGpuClocks(false) + changeAudioStatus(false) } override fun onResume() { super.onResume() + if (preferenceSettings.forceMaxGpuClocks) + GpuDriverHelper.forceMaxGpuClocks(true) + changeAudioStatus(true) if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { @@ -314,13 +322,15 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo super.onDestroy() shouldFinish = false - stopEmulation(false) - vibrators.forEach { (_, vibrator) -> vibrator.cancel() } - vibrators.clear() - // Stop forcing 60Hz on exit to allow the skyline UI to run at high refresh rates getSystemService()?.unregisterDisplayListener(this) force60HzRefreshRate(false) + if (preferenceSettings.forceMaxGpuClocks) + GpuDriverHelper.forceMaxGpuClocks(false) + + stopEmulation(false) + vibrators.forEach { (_, vibrator) -> vibrator.cancel() } + vibrators.clear() } override fun surfaceCreated(holder : SurfaceHolder) { diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index 93237ce8..c96a6dbf 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -36,6 +36,7 @@ import emu.skyline.loader.AppEntry import emu.skyline.loader.LoaderResult import emu.skyline.loader.RomFormat import emu.skyline.provider.DocumentsProvider +import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.PreferenceSettings import emu.skyline.utils.WindowInsetsHelper import javax.inject.Inject @@ -278,6 +279,10 @@ class MainActivity : AppCompatActivity() { override fun onResume() { super.onResume() + // Try to return to normal GPU clocks upon resuming back to main activity, to avoid GPU being stuck at max clocks after a crash + if (preferenceSettings.forceMaxGpuClocks) + GpuDriverHelper.forceMaxGpuClocks(false) + var layoutTypeChanged = false for (appViewItem in adapter.allItems.filterIsInstance(AppViewItem::class.java)) { if (layoutType != appViewItem.layoutType) { diff --git a/app/src/main/java/emu/skyline/SettingsActivity.kt b/app/src/main/java/emu/skyline/SettingsActivity.kt index a3f789ab..4c1bac03 100644 --- a/app/src/main/java/emu/skyline/SettingsActivity.kt +++ b/app/src/main/java/emu/skyline/SettingsActivity.kt @@ -16,7 +16,9 @@ import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import emu.skyline.databinding.SettingsActivityBinding import emu.skyline.preference.IntegerListPreference +import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.WindowInsetsHelper +import emu.skyline.utils.sharedPreferences class SettingsActivity : AppCompatActivity() { val binding by lazy { SettingsActivityBinding.inflate(layoutInflater) } @@ -108,6 +110,13 @@ class SettingsActivity : AppCompatActivity() { findPreference("category_debug")?.isVisible = true + if (!GpuDriverHelper.supportsForceMaxGpuClocks()) { + val forceMaxGpuClocksPref = findPreference("force_max_gpu_clocks")!! + forceMaxGpuClocksPref.isSelectable = false + forceMaxGpuClocksPref.isChecked = false + forceMaxGpuClocksPref.summary = context!!.getString(R.string.force_max_gpu_clocks_desc_unsupported) + } + resources.getStringArray(R.array.credits_entries).asIterable().shuffled().forEach { findPreference("category_credits")?.addPreference(Preference(context!!).apply { title = it diff --git a/app/src/main/java/emu/skyline/utils/GpuDriverHelper.kt b/app/src/main/java/emu/skyline/utils/GpuDriverHelper.kt index bade4be1..9d949a66 100644 --- a/app/src/main/java/emu/skyline/utils/GpuDriverHelper.kt +++ b/app/src/main/java/emu/skyline/utils/GpuDriverHelper.kt @@ -36,6 +36,17 @@ interface GpuDriverHelper { */ external fun supportsCustomDriverLoading() : Boolean + /** + * Queries the driver for manual max clock forcing support + */ + external fun supportsForceMaxGpuClocks() : Boolean + + /** + * Calls into the driver to force the GPU to run at the maximum possible clock speed + * @param force Whether to enable or disable the forced clocks + */ + external fun forceMaxGpuClocks(enable : Boolean) + /** * Returns the list of installed gpu drivers. * @return A map from the folder the driver is installed to the metadata of the driver diff --git a/app/src/main/java/emu/skyline/utils/PreferenceSettings.kt b/app/src/main/java/emu/skyline/utils/PreferenceSettings.kt index 812aa2ba..f49ab807 100644 --- a/app/src/main/java/emu/skyline/utils/PreferenceSettings.kt +++ b/app/src/main/java/emu/skyline/utils/PreferenceSettings.kt @@ -40,6 +40,7 @@ class PreferenceSettings @Inject constructor(@ApplicationContext private val con // GPU var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER) var executorSlotCountScale by sharedPreferences(context, 6) + var forceMaxGpuClocks by sharedPreferences(context, false) // Hacks var enableFastGpuReadbackHack by sharedPreferences(context, false) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 176f539f..4a07a092 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -77,6 +77,9 @@ Allow UI elements to be drawn in the cutout area Executor Slot Count Scale Scale controlling the maximum number of simultaneous GPU executions (Higher may sometimes perform better but will use more RAM) + Force Maximum GPU Clocks + Forces the GPU to run at its maximum possible clock speed (May cause excessive heating and power usage) + Your device does not support forcing maximum GPU clocks Hacks Enable fast GPU readback diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index ee57b9e6..cef2284a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -138,6 +138,11 @@ app:key="executor_slot_count_scale" app:title="@string/executor_slot_count_scale" app:showSeekBarValue="true" /> +