diff --git a/app/src/main/cpp/skyline/common/android_settings.h b/app/src/main/cpp/skyline/common/android_settings.h index ac17b8eb..a3f766e4 100644 --- a/app/src/main/cpp/skyline/common/android_settings.h +++ b/app/src/main/cpp/skyline/common/android_settings.h @@ -36,6 +36,8 @@ namespace skyline { systemLanguage = ktSettings.GetInt("systemLanguage"); forceTripleBuffering = ktSettings.GetBool("forceTripleBuffering"); disableFrameThrottling = ktSettings.GetBool("disableFrameThrottling"); + gpuDriver = ktSettings.GetString("gpuDriver"); + gpuDriverLibraryName = ktSettings.GetString("gpuDriverLibraryName"); }; }; } diff --git a/app/src/main/cpp/skyline/common/settings.h b/app/src/main/cpp/skyline/common/settings.h index d1962726..79a62c41 100644 --- a/app/src/main/cpp/skyline/common/settings.h +++ b/app/src/main/cpp/skyline/common/settings.h @@ -67,6 +67,10 @@ namespace skyline { Setting forceTripleBuffering; //!< If the presentation engine should always triple buffer even if the swapchain supports double buffering Setting disableFrameThrottling; //!< Allow the guest to submit frames without any blocking calls + // GPU + Setting gpuDriver; //!< The label of the GPU driver to use + Setting gpuDriverLibraryName; //!< The name of the GPU driver library to use + Settings() = default; virtual ~Settings() = default; diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index da5bc1c6..3f5bd5ad 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "gpu.h" namespace skyline::gpu { @@ -332,30 +333,29 @@ namespace skyline::gpu { } static PFN_vkGetInstanceProcAddr LoadVulkanDriver(const DeviceState &state) { - // Try turnip first, if not then fallback to regular with file redirect then plain dlopen - auto libvulkanHandle{adrenotools_open_libvulkan( - RTLD_NOW, - ADRENOTOOLS_DRIVER_CUSTOM, - nullptr, // We require Android 10 so don't need to supply - state.os->nativeLibraryPath.c_str(), - (state.os->privateAppFilesPath + "gpu/turnip/").c_str(), - "libvulkan_freedreno.so", - nullptr - )}; - if (!libvulkanHandle) { + void *libvulkanHandle{}; + + // If the user has selected a custom driver, try to load it + if (!(*state.settings->gpuDriver).empty()) { libvulkanHandle = adrenotools_open_libvulkan( RTLD_NOW, - ADRENOTOOLS_DRIVER_FILE_REDIRECT, + ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM, nullptr, // We require Android 10 so don't need to supply state.os->nativeLibraryPath.c_str(), - nullptr, - nullptr, + (state.os->privateAppFilesPath + "gpu_drivers/" + *state.settings->gpuDriver + "/").c_str(), + (*state.settings->gpuDriverLibraryName).c_str(), (state.os->publicAppFilesPath + "gpu/vk_file_redirect/").c_str() ); - if (!libvulkanHandle) - libvulkanHandle = dlopen("libvulkan.so", RTLD_NOW); + + if (!libvulkanHandle) { + char *error = dlerror(); + Logger::Warn("Failed to load custom Vulkan driver {}/{}: {}", *state.settings->gpuDriver, *state.settings->gpuDriverLibraryName, error ? error : ""); + } } + if (!libvulkanHandle) + libvulkanHandle = dlopen("libvulkan.so", RTLD_NOW); + return reinterpret_cast(dlsym(libvulkanHandle, "vkGetInstanceProcAddr")); } diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index 9a071335..1d6cc37c 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -28,16 +28,16 @@ import emu.skyline.applet.swkbd.SoftwareKeyboardDialog import emu.skyline.databinding.EmuActivityBinding import emu.skyline.input.* import emu.skyline.loader.getRomFormat -import emu.skyline.utils.PreferenceSettings import emu.skyline.utils.ByteBufferSerializable +import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.NativeSettings +import emu.skyline.utils.PreferenceSettings import java.nio.ByteBuffer import java.nio.ByteOrder import java.util.concurrent.FutureTask import javax.inject.Inject import kotlin.math.abs - @AndroidEntryPoint class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTouchListener, DisplayManager.DisplayListener { companion object { @@ -248,8 +248,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo val romType = getRomFormat(rom, contentResolver).ordinal val romFd = contentResolver.openFileDescriptor(rom, "r")!! + GpuDriverHelper.ensureFileRedirectDir(this) emulationThread = Thread { - executeApplication(rom.toString(), romType, romFd.detachFd(), NativeSettings(preferenceSettings), applicationContext.getPublicFilesDir().canonicalPath + "/", applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets) + executeApplication(rom.toString(), romType, romFd.detachFd(), NativeSettings(this, preferenceSettings), applicationContext.getPublicFilesDir().canonicalPath + "/", applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets) returnFromEmulation() } diff --git a/app/src/main/java/emu/skyline/utils/NativeSettings.kt b/app/src/main/java/emu/skyline/utils/NativeSettings.kt index 15f52da8..3e9e70b7 100644 --- a/app/src/main/java/emu/skyline/utils/NativeSettings.kt +++ b/app/src/main/java/emu/skyline/utils/NativeSettings.kt @@ -5,15 +5,19 @@ package emu.skyline.utils +import android.content.Context + /** * The settings that will be passed to libskyline when running and executable */ -class NativeSettings(pref: PreferenceSettings) { +class NativeSettings(context : Context, pref : PreferenceSettings) { var isDocked : Boolean = pref.isDocked var usernameValue : String = pref.usernameValue var systemLanguage : Int = pref.systemLanguage var forceTripleBuffering : Boolean = pref.forceTripleBuffering var disableFrameThrottling : Boolean = pref.disableFrameThrottling + var gpuDriver : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else pref.gpuDriver + var gpuDriverLibraryName : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else GpuDriverHelper.getLibraryName(context, pref.gpuDriver) /** * Updates settings in libskyline during emulation