From 4667a47e9bcb561dc48411db125a774dc194e80c Mon Sep 17 00:00:00 2001 From: DH Date: Tue, 18 Mar 2025 05:00:46 +0300 Subject: [PATCH] android: add custom driver support --- .gitmodules | 3 + 3rdparty/CMakeLists.txt | 8 ++ 3rdparty/libadrenotools | 1 + rpcs3/rpcs3/Emu/CMakeLists.txt | 1 + rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.cpp | 11 +++ rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.h | 2 + rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.cpp | 96 ++++++++++++++++++--- rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.h | 3 + 8 files changed, 111 insertions(+), 14 deletions(-) create mode 160000 3rdparty/libadrenotools diff --git a/.gitmodules b/.gitmodules index a8df186f9..6aeca545e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -136,3 +136,6 @@ path = rpcs3/3rdparty/json url = ../../nlohmann/json.git ignore = dirty +[submodule "3rdparty/libadrenotools"] + path = 3rdparty/libadrenotools + url = ../../bylaws/libadrenotools.git diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index c6d576a8b..c35177eaf 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -343,6 +343,13 @@ if(USE_SYSTEM_LIBUSB) else() add_library(3rdparty::libusb ALIAS usb-1.0-static) endif() + +if (ANDROID) + add_subdirectory(libadrenotools) +else() + add_library(adrenotools INTERFACE) +endif() + add_library(3rdparty::zlib ALIAS 3rdparty_zlib) add_library(3rdparty::zstd ALIAS 3rdparty_zstd) add_library(3rdparty::7zip ALIAS 3rdparty_7zip) @@ -370,3 +377,4 @@ add_library(3rdparty::rtmidi ALIAS rtmidi) add_library(3rdparty::opencv ALIAS ${OPENCV_TARGET}) add_library(3rdparty::fusion ALIAS Fusion) add_library(3rdparty::json ALIAS 3rdparty_json) +add_library(3rdparty::adrenotools ALIAS adrenotools) diff --git a/3rdparty/libadrenotools b/3rdparty/libadrenotools new file mode 160000 index 000000000..8fae8ce25 --- /dev/null +++ b/3rdparty/libadrenotools @@ -0,0 +1 @@ +Subproject commit 8fae8ce254dfc1344527e05301e43f37dea2df80 diff --git a/rpcs3/rpcs3/Emu/CMakeLists.txt b/rpcs3/rpcs3/Emu/CMakeLists.txt index e2f4e320e..8738f0d72 100644 --- a/rpcs3/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/rpcs3/Emu/CMakeLists.txt @@ -178,6 +178,7 @@ target_link_libraries(rpcs3_emu 3rdparty::soundtouch 3rdparty::miniupnpc 3rdparty::json + 3rdparty::adrenotools ) # Cell diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.cpp index 35c94e35c..448ca8f35 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -245,6 +245,17 @@ namespace vk return props.deviceName; } + std::string physical_device::get_driver_name() const + { + return driver_properties.driverName; + } + + std::string physical_device::get_driver_vk_version() const + { + auto version = driver_properties.conformanceVersion; + return fmt::format("%u.%u.%u.%d", version.major, version.minor, version.subminor, version.patch); + } + driver_vendor physical_device::get_driver_vendor() const { #ifdef __APPLE__ diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.h b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.h index febd132d7..3d0a38708 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.h +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/device.h @@ -108,6 +108,8 @@ namespace vk void create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions); std::string get_name() const; + std::string get_driver_name() const; + std::string get_driver_vk_version() const; driver_vendor get_driver_vendor() const; std::string get_driver_version() const; diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.cpp b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.cpp index 5df7eec5b..23a9c8e0e 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.cpp +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.cpp @@ -1,32 +1,49 @@ #include "stdafx.h" #include "instance.h" +#ifdef ANDROID +#include +#include "libadrenotools/include/adrenotools/priv.h" +#include +#include +#include +#endif + +#ifdef ANDROID +#define GET_VK_PFN(lib, name) (lib == nullptr ? &name : reinterpret_cast(dlsym(lib, #name))) +#else +#define GET_VK_PFN(lib, name) (&name) +#endif + namespace vk { + static PFN_vkEnumerateInstanceExtensionProperties _vkEnumerateInstanceExtensionProperties; + static PFN_vkEnumerateDeviceExtensionProperties _vkEnumerateDeviceExtensionProperties; + // Supported extensions supported_extensions::supported_extensions(enumeration_class _class, const char* layer_name, VkPhysicalDevice pdev) { u32 count; if (_class == enumeration_class::instance) { - if (vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS) + if (_vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS) return; } else { ensure(pdev); - if (vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, nullptr) != VK_SUCCESS) + if (_vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, nullptr) != VK_SUCCESS) return; } m_vk_exts.resize(count); if (_class == enumeration_class::instance) { - vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data()); + _vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data()); } else { - vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, m_vk_exts.data()); + _vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, m_vk_exts.data()); } } @@ -56,12 +73,19 @@ namespace vk if (m_surface) { - vkDestroySurfaceKHR(m_instance, m_surface, nullptr); + GET_VK_PFN(m_vk_loader, vkDestroySurfaceKHR)(m_instance, m_surface, nullptr); m_surface = VK_NULL_HANDLE; } - vkDestroyInstance(m_instance, nullptr); + GET_VK_PFN(m_vk_loader, vkDestroyInstance)(m_instance, nullptr); m_instance = VK_NULL_HANDLE; + +#ifdef ANDROID + if (m_vk_loader != nullptr) + { + ::dlclose(m_vk_loader); + } +#endif } void instance::enable_debugging() @@ -70,8 +94,10 @@ namespace vk PFN_vkDebugReportCallbackEXT callback = vk::dbgFunc; - _vkCreateDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkCreateDebugReportCallbackEXT")); - _vkDestroyDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkDestroyDebugReportCallbackEXT")); + auto _vkGetInstanceProcAddr = GET_VK_PFN(m_vk_loader, vkGetInstanceProcAddr); + + _vkCreateDebugReportCallback = reinterpret_cast(_vkGetInstanceProcAddr(m_instance, "vkCreateDebugReportCallbackEXT")); + _vkDestroyDebugReportCallback = reinterpret_cast(_vkGetInstanceProcAddr(m_instance, "vkDestroyDebugReportCallbackEXT")); VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; @@ -87,6 +113,48 @@ namespace vk #endif bool instance::create(const char* app_name, bool fast) { +#ifdef ANDROID + auto custom_driver_path = g_cfg.video.vk.custom_driver_path.to_string(); + if (!custom_driver_path.empty()) + { + rsx_log.warning("Loading custom driver %s", custom_driver_path); + + auto meta = nlohmann::json::parse(std::ifstream(custom_driver_path + "/meta.json")); + + if (meta.contains("libraryName")) + { + auto library_name = meta["libraryName"].get(); + rsx_log.warning("Custom driver: library name %s", library_name); + + auto hook_dir = g_cfg.video.vk.custom_driver_hook_dir.to_string(); + rsx_log.warning("Custom driver: hook dir %s", hook_dir); + + + ::dlerror(); + m_vk_loader = adrenotools_open_libvulkan( + RTLD_NOW, ADRENOTOOLS_DRIVER_CUSTOM, + nullptr, (hook_dir + "/").c_str(), + (custom_driver_path + "/").c_str(), library_name.c_str(), + nullptr, nullptr); + + if (m_vk_loader == nullptr) + { + rsx_log.error("Failed to load custom driver at '%s': %s", custom_driver_path, ::dlerror()); + } + else + { + rsx_log.error("Custom driver at '%s' successfully loaded", custom_driver_path); + } + } + else + { + rsx_log.error("Custom driver load error: Invalid meta.json at %s", custom_driver_path); + } + } +#endif + _vkEnumerateInstanceExtensionProperties = GET_VK_PFN(m_vk_loader, vkEnumerateInstanceExtensionProperties); + _vkEnumerateDeviceExtensionProperties = GET_VK_PFN(m_vk_loader, vkEnumerateDeviceExtensionProperties); + // Initialize a vulkan instance VkApplicationInfo app = {}; @@ -207,7 +275,7 @@ namespace vk instance_info.ppEnabledExtensionNames = fast ? nullptr : extensions.data(); instance_info.pNext = next_info; - if (VkResult result = vkCreateInstance(&instance_info, nullptr, &m_instance); result != VK_SUCCESS) + if (VkResult result = GET_VK_PFN(m_vk_loader, vkCreateInstance)(&instance_info, nullptr, &m_instance); result != VK_SUCCESS) { if (result == VK_ERROR_LAYER_NOT_PRESENT) { @@ -238,7 +306,7 @@ namespace vk { u32 num_gpus; // This may fail on unsupported drivers, so just assume no devices - if (vkEnumeratePhysicalDevices(m_instance, &num_gpus, nullptr) != VK_SUCCESS) + if (GET_VK_PFN(m_vk_loader, vkEnumeratePhysicalDevices)(m_instance, &num_gpus, nullptr) != VK_SUCCESS) return gpus; if (gpus.size() != num_gpus) @@ -246,7 +314,7 @@ namespace vk std::vector pdevs(num_gpus); gpus.resize(num_gpus); - CHECK_RESULT(vkEnumeratePhysicalDevices(m_instance, &num_gpus, pdevs.data())); + CHECK_RESULT(GET_VK_PFN(m_vk_loader, vkEnumeratePhysicalDevices)(m_instance, &num_gpus, pdevs.data())); for (u32 i = 0; i < num_gpus; ++i) gpus[i].create(m_instance, pdevs[i], extensions_loaded); @@ -269,7 +337,7 @@ namespace vk for (u32 index = 0; index < device_queues; index++) { - vkGetPhysicalDeviceSurfaceSupportKHR(dev, index, m_surface, &supports_present[index]); + GET_VK_PFN(m_vk_loader, vkGetPhysicalDeviceSurfaceSupportKHR)(dev, index, m_surface, &supports_present[index]); } u32 graphics_queue_idx = -1; @@ -338,10 +406,10 @@ namespace vk // Get the list of VkFormat's that are supported: u32 formatCount; - CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(dev, m_surface, &formatCount, nullptr)); + CHECK_RESULT(GET_VK_PFN(m_vk_loader,vkGetPhysicalDeviceSurfaceFormatsKHR)(dev, m_surface, &formatCount, nullptr)); std::vector surfFormats(formatCount); - CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(dev, m_surface, &formatCount, surfFormats.data())); + CHECK_RESULT(GET_VK_PFN(m_vk_loader,vkGetPhysicalDeviceSurfaceFormatsKHR)(dev, m_surface, &formatCount, surfFormats.data())); VkFormat format; VkColorSpaceKHR color_space; diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.h b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.h index b4b87b1a7..2266ac72e 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.h +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/instance.h @@ -36,6 +36,9 @@ namespace vk std::vector gpus; VkInstance m_instance = VK_NULL_HANDLE; VkSurfaceKHR m_surface = VK_NULL_HANDLE; +#ifdef ANDROID + void *m_vk_loader = nullptr; +#endif PFN_vkDestroyDebugReportCallbackEXT _vkDestroyDebugReportCallback = nullptr; PFN_vkCreateDebugReportCallbackEXT _vkCreateDebugReportCallback = nullptr;