VideoBackends:Vulkan: Allow loading custom drivers on Android

... using libadrenotools
This commit is contained in:
Robin Kertels
2023-06-01 00:05:06 +02:00
parent 35bb663c2a
commit 23bebc5270
24 changed files with 399 additions and 29 deletions

View File

@ -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