diff options
| author | Robin Kertels <robin.kertels@gmail.com> | 2023-06-01 00:05:06 +0200 |
|---|---|---|
| committer | Robin Kertels <robin.kertels@gmail.com> | 2023-06-11 13:52:34 +0200 |
| commit | 23bebc5270bfd5a149aeb8bb5a3a2dd4433bd5e1 (patch) | |
| tree | 45e378d45f19381a1a92a5e71ee38780f78cc687 /Source/Core/VideoBackends/Vulkan | |
| parent | 35bb663c2abfba0208931b85d779ed5a0084c7e8 (diff) | |
VideoBackends:Vulkan: Allow loading custom drivers on Android
... using libadrenotools
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/VulkanContext.cpp | 11 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp | 62 | ||||
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/VulkanLoader.h | 10 |
4 files changed, 84 insertions, 7 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/CMakeLists.txt b/Source/Core/VideoBackends/Vulkan/CMakeLists.txt index 7abf9a038b..ec9e1b51cb 100644 --- a/Source/Core/VideoBackends/Vulkan/CMakeLists.txt +++ b/Source/Core/VideoBackends/Vulkan/CMakeLists.txt @@ -48,11 +48,19 @@ PRIVATE xxhash ) +if (ANDROID AND _M_ARM_64) + target_link_libraries(videovulkan + PRIVATE + adrenotools + ) +endif() + # Only include the Vulkan headers when building the Vulkan backend target_include_directories(videovulkan PRIVATE ${CMAKE_SOURCE_DIR}/Externals/Vulkan/Include ${CMAKE_SOURCE_DIR}/Externals/VulkanMemoryAllocator/include + ${CMAKE_SOURCE_DIR}/Externals/libadrenotools/include ) if(MSVC) diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 5b5f2ffaee..ed4d749878 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -143,7 +143,18 @@ VkInstance VulkanContext::CreateVulkanInstance(WindowSystemType wstype, bool ena { // The device itself may not support 1.1, so we check that before using any 1.1 functionality. app_info.apiVersion = VK_MAKE_VERSION(1, 1, 0); + WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.1, supported: {}.{}", + VK_VERSION_MAJOR(supported_api_version), + VK_VERSION_MINOR(supported_api_version)); } + else + { + WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.0"); + } + } + else + { + WARN_LOG_FMT(HOST_GPU, "Using Vulkan 1.0"); } *out_vk_api_version = app_info.apiVersion; diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp index 9b62244dfd..34c531fc2f 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp @@ -8,11 +8,18 @@ #include <cstdarg> #include <cstdlib> +#if defined(ANDROID) +#include <adrenotools/driver.h> +#include <dlfcn.h> +#endif + #include "Common/CommonFuncs.h" #include "Common/DynamicLibrary.h" #include "Common/FileUtil.h" #include "Common/StringUtil.h" +#include "VideoCommon/VideoConfig.h" + #define VULKAN_MODULE_ENTRY_POINT(name, required) PFN_##name name; #define VULKAN_INSTANCE_ENTRY_POINT(name, required) PFN_##name name; #define VULKAN_DEVICE_ENTRY_POINT(name, required) PFN_##name name; @@ -36,9 +43,9 @@ static void ResetVulkanLibraryFunctionPointers() static Common::DynamicLibrary s_vulkan_module; -static bool OpenVulkanLibrary() +static bool OpenVulkanLibrary(bool force_system_library) { -#ifdef __APPLE__ +#if defined(__APPLE__) // Check if a path to a specific Vulkan library has been specified. char* libvulkan_env = getenv("LIBVULKAN_PATH"); if (libvulkan_env && s_vulkan_module.Open(libvulkan_env)) @@ -48,6 +55,35 @@ static bool OpenVulkanLibrary() std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libMoltenVK.dylib"; return s_vulkan_module.Open(filename.c_str()); #else + +#if defined(ANDROID) && _M_ARM_64 + const std::string& driver_lib_name = g_Config.customDriverLibraryName; + + if (!force_system_library && !driver_lib_name.empty() && SupportsCustomDriver()) + { + std::string tmp_dir = File::GetGpuDriverDirectory(D_GPU_DRIVERS_TMP); + std::string hook_dir = File::GetGpuDriverDirectory(D_GPU_DRIVERS_HOOKS); + std::string file_redirect_dir = File::GetGpuDriverDirectory(D_GPU_DRIVERS_FILE_REDIRECT); + std::string driver_dir = File::GetGpuDriverDirectory(D_GPU_DRIVERS_EXTRACTED); + INFO_LOG_FMT(HOST_GPU, "Loading driver: {}", driver_lib_name); + + s_vulkan_module = adrenotools_open_libvulkan( + RTLD_NOW, ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM, tmp_dir.c_str(), + hook_dir.c_str(), driver_dir.c_str(), driver_lib_name.c_str(), file_redirect_dir.c_str(), + nullptr); + if (s_vulkan_module.IsOpen()) + { + INFO_LOG_FMT(HOST_GPU, "Successfully loaded driver: {}", driver_lib_name); + return true; + } + else + { + WARN_LOG_FMT(HOST_GPU, "Loading driver {} failed.", driver_lib_name); + } + } +#endif + + WARN_LOG_FMT(HOST_GPU, "Loading system driver"); std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); if (s_vulkan_module.Open(filename.c_str())) return true; @@ -58,9 +94,9 @@ static bool OpenVulkanLibrary() #endif } -bool LoadVulkanLibrary() +bool LoadVulkanLibrary(bool force_system_library) { - if (!s_vulkan_module.IsOpen() && !OpenVulkanLibrary()) + if (!s_vulkan_module.IsOpen() && !OpenVulkanLibrary(force_system_library)) return false; #define VULKAN_MODULE_ENTRY_POINT(name, required) \ @@ -91,7 +127,7 @@ bool LoadVulkanInstanceFunctions(VkInstance instance) *func_ptr = vkGetInstanceProcAddr(instance, name); if (!(*func_ptr) && is_required) { - ERROR_LOG_FMT(VIDEO, "Vulkan: Failed to load required instance function {}", name); + ERROR_LOG_FMT(HOST_GPU, "Vulkan: Failed to load required instance function {}", name); required_functions_missing = true; } }; @@ -111,7 +147,7 @@ bool LoadVulkanDeviceFunctions(VkDevice device) *func_ptr = vkGetDeviceProcAddr(device, name); if (!(*func_ptr) && is_required) { - ERROR_LOG_FMT(VIDEO, "Vulkan: Failed to load required device function {}", name); + ERROR_LOG_FMT(HOST_GPU, "Vulkan: Failed to load required device function {}", name); required_functions_missing = true; } }; @@ -212,4 +248,18 @@ void LogVulkanResult(Common::Log::LogLevel level, const char* func_name, VkResul static_cast<int>(res), VkResultToString(res)); } +#ifdef ANDROID +static bool CheckKgslPresent() +{ + constexpr auto KgslPath{"/dev/kgsl-3d0"}; + + return access(KgslPath, F_OK) == 0; +} + +bool SupportsCustomDriver() +{ + return android_get_device_api_level() >= 28 && CheckKgslPresent(); +} +#endif + } // namespace Vulkan diff --git a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h index 652b512dd4..d1a426d952 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanLoader.h +++ b/Source/Core/VideoBackends/Vulkan/VulkanLoader.h @@ -23,6 +23,10 @@ #include "vulkan/vulkan.h" +#ifdef ANDROID +#include <unistd.h> +#endif + // Currently, exclusive fullscreen is only supported on Windows. #if defined(WIN32) #define SUPPORTS_VULKAN_EXCLUSIVE_FULLSCREEN 1 @@ -78,11 +82,15 @@ namespace Vulkan { -bool LoadVulkanLibrary(); +bool LoadVulkanLibrary(bool force_system_library = false); bool LoadVulkanInstanceFunctions(VkInstance instance); bool LoadVulkanDeviceFunctions(VkDevice device); void UnloadVulkanLibrary(); +#ifdef ANDROID +bool SupportsCustomDriver(); +#endif + const char* VkResultToString(VkResult res); void LogVulkanResult(Common::Log::LogLevel level, const char* func_name, VkResult res, const char* msg); |
