android: add custom driver support

This commit is contained in:
DH 2025-03-18 05:00:46 +03:00
parent 6ae10eb152
commit 4667a47e9b
8 changed files with 111 additions and 14 deletions

3
.gitmodules vendored
View file

@ -136,3 +136,6 @@
path = rpcs3/3rdparty/json path = rpcs3/3rdparty/json
url = ../../nlohmann/json.git url = ../../nlohmann/json.git
ignore = dirty ignore = dirty
[submodule "3rdparty/libadrenotools"]
path = 3rdparty/libadrenotools
url = ../../bylaws/libadrenotools.git

View file

@ -343,6 +343,13 @@ if(USE_SYSTEM_LIBUSB)
else() else()
add_library(3rdparty::libusb ALIAS usb-1.0-static) add_library(3rdparty::libusb ALIAS usb-1.0-static)
endif() endif()
if (ANDROID)
add_subdirectory(libadrenotools)
else()
add_library(adrenotools INTERFACE)
endif()
add_library(3rdparty::zlib ALIAS 3rdparty_zlib) add_library(3rdparty::zlib ALIAS 3rdparty_zlib)
add_library(3rdparty::zstd ALIAS 3rdparty_zstd) add_library(3rdparty::zstd ALIAS 3rdparty_zstd)
add_library(3rdparty::7zip ALIAS 3rdparty_7zip) 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::opencv ALIAS ${OPENCV_TARGET})
add_library(3rdparty::fusion ALIAS Fusion) add_library(3rdparty::fusion ALIAS Fusion)
add_library(3rdparty::json ALIAS 3rdparty_json) add_library(3rdparty::json ALIAS 3rdparty_json)
add_library(3rdparty::adrenotools ALIAS adrenotools)

1
3rdparty/libadrenotools vendored Submodule

@ -0,0 +1 @@
Subproject commit 8fae8ce254dfc1344527e05301e43f37dea2df80

View file

@ -178,6 +178,7 @@ target_link_libraries(rpcs3_emu
3rdparty::soundtouch 3rdparty::soundtouch
3rdparty::miniupnpc 3rdparty::miniupnpc
3rdparty::json 3rdparty::json
3rdparty::adrenotools
) )
# Cell # Cell

View file

@ -245,6 +245,17 @@ namespace vk
return props.deviceName; 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 driver_vendor physical_device::get_driver_vendor() const
{ {
#ifdef __APPLE__ #ifdef __APPLE__

View file

@ -108,6 +108,8 @@ namespace vk
void create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions); void create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions);
std::string get_name() const; std::string get_name() const;
std::string get_driver_name() const;
std::string get_driver_vk_version() const;
driver_vendor get_driver_vendor() const; driver_vendor get_driver_vendor() const;
std::string get_driver_version() const; std::string get_driver_version() const;

View file

@ -1,32 +1,49 @@
#include "stdafx.h" #include "stdafx.h"
#include "instance.h" #include "instance.h"
#ifdef ANDROID
#include <fstream>
#include "libadrenotools/include/adrenotools/priv.h"
#include <libadrenotools/include/adrenotools/driver.h>
#include <dlfcn.h>
#include <nlohmann/json.hpp>
#endif
#ifdef ANDROID
#define GET_VK_PFN(lib, name) (lib == nullptr ? &name : reinterpret_cast<PFN_##name>(dlsym(lib, #name)))
#else
#define GET_VK_PFN(lib, name) (&name)
#endif
namespace vk namespace vk
{ {
static PFN_vkEnumerateInstanceExtensionProperties _vkEnumerateInstanceExtensionProperties;
static PFN_vkEnumerateDeviceExtensionProperties _vkEnumerateDeviceExtensionProperties;
// Supported extensions // Supported extensions
supported_extensions::supported_extensions(enumeration_class _class, const char* layer_name, VkPhysicalDevice pdev) supported_extensions::supported_extensions(enumeration_class _class, const char* layer_name, VkPhysicalDevice pdev)
{ {
u32 count; u32 count;
if (_class == enumeration_class::instance) if (_class == enumeration_class::instance)
{ {
if (vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS) if (_vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS)
return; return;
} }
else else
{ {
ensure(pdev); ensure(pdev);
if (vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, nullptr) != VK_SUCCESS) if (_vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, nullptr) != VK_SUCCESS)
return; return;
} }
m_vk_exts.resize(count); m_vk_exts.resize(count);
if (_class == enumeration_class::instance) if (_class == enumeration_class::instance)
{ {
vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data()); _vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data());
} }
else 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) 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; m_surface = VK_NULL_HANDLE;
} }
vkDestroyInstance(m_instance, nullptr); GET_VK_PFN(m_vk_loader, vkDestroyInstance)(m_instance, nullptr);
m_instance = VK_NULL_HANDLE; m_instance = VK_NULL_HANDLE;
#ifdef ANDROID
if (m_vk_loader != nullptr)
{
::dlclose(m_vk_loader);
}
#endif
} }
void instance::enable_debugging() void instance::enable_debugging()
@ -70,8 +94,10 @@ namespace vk
PFN_vkDebugReportCallbackEXT callback = vk::dbgFunc; PFN_vkDebugReportCallbackEXT callback = vk::dbgFunc;
_vkCreateDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(vkGetInstanceProcAddr(m_instance, "vkCreateDebugReportCallbackEXT")); auto _vkGetInstanceProcAddr = GET_VK_PFN(m_vk_loader, vkGetInstanceProcAddr);
_vkDestroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(vkGetInstanceProcAddr(m_instance, "vkDestroyDebugReportCallbackEXT"));
_vkCreateDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(_vkGetInstanceProcAddr(m_instance, "vkCreateDebugReportCallbackEXT"));
_vkDestroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(_vkGetInstanceProcAddr(m_instance, "vkDestroyDebugReportCallbackEXT"));
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {}; VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
@ -87,6 +113,48 @@ namespace vk
#endif #endif
bool instance::create(const char* app_name, bool fast) 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<std::string>();
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 // Initialize a vulkan instance
VkApplicationInfo app = {}; VkApplicationInfo app = {};
@ -207,7 +275,7 @@ namespace vk
instance_info.ppEnabledExtensionNames = fast ? nullptr : extensions.data(); instance_info.ppEnabledExtensionNames = fast ? nullptr : extensions.data();
instance_info.pNext = next_info; 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) if (result == VK_ERROR_LAYER_NOT_PRESENT)
{ {
@ -238,7 +306,7 @@ namespace vk
{ {
u32 num_gpus; u32 num_gpus;
// This may fail on unsupported drivers, so just assume no devices // 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; return gpus;
if (gpus.size() != num_gpus) if (gpus.size() != num_gpus)
@ -246,7 +314,7 @@ namespace vk
std::vector<VkPhysicalDevice> pdevs(num_gpus); std::vector<VkPhysicalDevice> pdevs(num_gpus);
gpus.resize(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) for (u32 i = 0; i < num_gpus; ++i)
gpus[i].create(m_instance, pdevs[i], extensions_loaded); gpus[i].create(m_instance, pdevs[i], extensions_loaded);
@ -269,7 +337,7 @@ namespace vk
for (u32 index = 0; index < device_queues; index++) 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; u32 graphics_queue_idx = -1;
@ -338,10 +406,10 @@ namespace vk
// Get the list of VkFormat's that are supported: // Get the list of VkFormat's that are supported:
u32 formatCount; 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<VkSurfaceFormatKHR> surfFormats(formatCount); std::vector<VkSurfaceFormatKHR> 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; VkFormat format;
VkColorSpaceKHR color_space; VkColorSpaceKHR color_space;

View file

@ -36,6 +36,9 @@ namespace vk
std::vector<physical_device> gpus; std::vector<physical_device> gpus;
VkInstance m_instance = VK_NULL_HANDLE; VkInstance m_instance = VK_NULL_HANDLE;
VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceKHR m_surface = VK_NULL_HANDLE;
#ifdef ANDROID
void *m_vk_loader = nullptr;
#endif
PFN_vkDestroyDebugReportCallbackEXT _vkDestroyDebugReportCallback = nullptr; PFN_vkDestroyDebugReportCallbackEXT _vkDestroyDebugReportCallback = nullptr;
PFN_vkCreateDebugReportCallbackEXT _vkCreateDebugReportCallback = nullptr; PFN_vkCreateDebugReportCallbackEXT _vkCreateDebugReportCallback = nullptr;