mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-31 10:09:36 -06:00
VideoBackends:Vulkan: Allow loading custom drivers on Android
... using libadrenotools
This commit is contained in:
@ -163,3 +163,10 @@
|
||||
|
||||
// Subdirs in Config
|
||||
#define GRAPHICSMOD_CONFIG_DIR "GraphicMods"
|
||||
|
||||
// GPU drivers
|
||||
#define GPU_DRIVERS "GpuDrivers"
|
||||
#define GPU_DRIVERS_EXTRACTED "Extracted"
|
||||
#define GPU_DRIVERS_TMP "Tmp"
|
||||
#define GPU_DRIVERS_HOOK "Hook"
|
||||
#define GPU_DRIVERS_FILE_REDIRECT "FileRedirect"
|
||||
|
@ -24,11 +24,22 @@ DynamicLibrary::DynamicLibrary(const char* filename)
|
||||
Open(filename);
|
||||
}
|
||||
|
||||
DynamicLibrary::DynamicLibrary(void* handle)
|
||||
{
|
||||
m_handle = handle;
|
||||
}
|
||||
|
||||
DynamicLibrary::~DynamicLibrary()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
DynamicLibrary& DynamicLibrary::operator=(void* handle)
|
||||
{
|
||||
m_handle = handle;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string DynamicLibrary::GetUnprefixedFilename(const char* filename)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
@ -21,6 +21,8 @@ public:
|
||||
// Automatically loads the specified library. Call IsOpen() to check validity before use.
|
||||
DynamicLibrary(const char* filename);
|
||||
|
||||
DynamicLibrary(void* handle);
|
||||
|
||||
// Closes the library.
|
||||
~DynamicLibrary();
|
||||
|
||||
@ -30,6 +32,8 @@ public:
|
||||
DynamicLibrary& operator=(const DynamicLibrary&) = delete;
|
||||
DynamicLibrary& operator=(DynamicLibrary&&) = delete;
|
||||
|
||||
DynamicLibrary& operator=(void*);
|
||||
|
||||
// Returns the specified library name with the platform-specific suffix added.
|
||||
static std::string GetUnprefixedFilename(const char* filename);
|
||||
|
||||
|
@ -66,6 +66,8 @@ namespace File
|
||||
{
|
||||
#ifdef ANDROID
|
||||
static std::string s_android_sys_directory;
|
||||
static std::string s_android_driver_directory;
|
||||
static std::string s_android_lib_directory;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -796,6 +798,34 @@ void SetSysDirectory(const std::string& path)
|
||||
s_android_sys_directory);
|
||||
s_android_sys_directory = path;
|
||||
}
|
||||
|
||||
void SetGpuDriverDirectories(const std::string& path, const std::string& lib_path)
|
||||
{
|
||||
INFO_LOG_FMT(COMMON, "Setting Driver directory to {} and library path to {}", path, lib_path);
|
||||
ASSERT_MSG(COMMON, s_android_driver_directory.empty(), "Driver directory already set to {}",
|
||||
s_android_driver_directory);
|
||||
ASSERT_MSG(COMMON, s_android_lib_directory.empty(), "Library directory already set to {}",
|
||||
s_android_lib_directory);
|
||||
s_android_driver_directory = path;
|
||||
s_android_lib_directory = lib_path;
|
||||
}
|
||||
|
||||
const std::string GetGpuDriverDirectory(unsigned int dir_index)
|
||||
{
|
||||
switch (dir_index)
|
||||
{
|
||||
case D_GPU_DRIVERS_EXTRACTED:
|
||||
return s_android_driver_directory + DIR_SEP GPU_DRIVERS_EXTRACTED DIR_SEP;
|
||||
case D_GPU_DRIVERS_TMP:
|
||||
return s_android_driver_directory + DIR_SEP GPU_DRIVERS_TMP DIR_SEP;
|
||||
case D_GPU_DRIVERS_HOOKS:
|
||||
return s_android_lib_directory;
|
||||
case D_GPU_DRIVERS_FILE_REDIRECT:
|
||||
return s_android_driver_directory + DIR_SEP GPU_DRIVERS_FILE_REDIRECT DIR_SEP;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static std::string s_user_paths[NUM_PATH_INDICES];
|
||||
|
@ -67,6 +67,10 @@ enum
|
||||
D_GBAUSER_IDX,
|
||||
D_GBASAVES_IDX,
|
||||
D_WIISDCARDSYNCFOLDER_IDX,
|
||||
D_GPU_DRIVERS_EXTRACTED,
|
||||
D_GPU_DRIVERS_TMP,
|
||||
D_GPU_DRIVERS_HOOKS,
|
||||
D_GPU_DRIVERS_FILE_REDIRECT,
|
||||
FIRST_FILE_USER_PATH_IDX,
|
||||
F_DOLPHINCONFIG_IDX = FIRST_FILE_USER_PATH_IDX,
|
||||
F_GCPADCONFIG_IDX,
|
||||
@ -228,6 +232,8 @@ const std::string& GetSysDirectory();
|
||||
|
||||
#ifdef ANDROID
|
||||
void SetSysDirectory(const std::string& path);
|
||||
void SetGpuDriverDirectories(const std::string& path, const std::string& lib_path);
|
||||
const std::string GetGpuDriverDirectory(unsigned int dir_index);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -111,6 +111,8 @@ const Info<bool> GFX_PREFER_GLES{{System::GFX, "Settings", "PreferGLES"}, false}
|
||||
|
||||
const Info<bool> GFX_MODS_ENABLE{{System::GFX, "Settings", "EnableMods"}, false};
|
||||
|
||||
const Info<std::string> GFX_DRIVER_LIB_NAME{{System::GFX, "Settings", "DriverLibName"}, ""};
|
||||
|
||||
// Graphics.Enhancements
|
||||
|
||||
const Info<TextureFilteringMode> GFX_ENHANCE_FORCE_TEXTURE_FILTERING{
|
||||
@ -171,4 +173,5 @@ const Info<bool> GFX_HACK_NO_MIPMAPPING{{System::GFX, "Hacks", "NoMipmapping"},
|
||||
// Graphics.GameSpecific
|
||||
|
||||
const Info<bool> GFX_PERF_QUERIES_ENABLE{{System::GFX, "GameSpecific", "PerfQueriesEnable"}, false};
|
||||
|
||||
} // namespace Config
|
||||
|
@ -148,4 +148,8 @@ extern const Info<bool> GFX_HACK_NO_MIPMAPPING;
|
||||
|
||||
extern const Info<bool> GFX_PERF_QUERIES_ENABLE;
|
||||
|
||||
// Android custom GPU drivers
|
||||
|
||||
extern const Info<std::string> GFX_DRIVER_LIB_NAME;
|
||||
|
||||
} // namespace Config
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -172,6 +172,8 @@ void VideoConfig::Refresh()
|
||||
bPerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
|
||||
|
||||
bGraphicMods = Config::Get(Config::GFX_MODS_ENABLE);
|
||||
|
||||
customDriverLibraryName = Config::Get(Config::GFX_DRIVER_LIB_NAME);
|
||||
}
|
||||
|
||||
void VideoConfig::VerifyValidity()
|
||||
|
@ -214,6 +214,9 @@ struct VideoConfig final
|
||||
int iShaderCompilerThreads = 0;
|
||||
int iShaderPrecompilerThreads = 0;
|
||||
|
||||
// Loading custom drivers on Android
|
||||
std::string customDriverLibraryName;
|
||||
|
||||
// Static config per API
|
||||
// TODO: Move this out of VideoConfig
|
||||
struct
|
||||
|
Reference in New Issue
Block a user