android: native: Add support for custom Vulkan driver loading.
This commit is contained in:
		| @@ -181,6 +181,8 @@ public final class NativeLibrary { | ||||
|  | ||||
|     public static native void SetAppDirectory(String directory); | ||||
|  | ||||
|     public static native void SetGpuDriverParameters(String hookLibDir, String customDriverDir, String customDriverName, String fileRedirectDir); | ||||
|  | ||||
|     public static native boolean ReloadKeys(); | ||||
|  | ||||
|     // Create the config.ini file. | ||||
|   | ||||
| @@ -13,6 +13,6 @@ add_library(yuzu-android SHARED | ||||
| set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) | ||||
|  | ||||
| target_link_libraries(yuzu-android PRIVATE audio_core common core input_common) | ||||
| target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics log) | ||||
| target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad inih jnigraphics adrenotools log) | ||||
|  | ||||
| set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} yuzu-android) | ||||
|   | ||||
| @@ -7,61 +7,62 @@ | ||||
| #include "jni/emu_window/emu_window.h" | ||||
|  | ||||
| void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | ||||
|     render_window = surface; | ||||
|     m_render_window = surface; | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { | ||||
|     const auto [touch_x, touch_y] = MapToTouchScreen(x, y); | ||||
|     input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); | ||||
|     m_input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnTouchMoved(int id, float x, float y) { | ||||
|     const auto [touch_x, touch_y] = MapToTouchScreen(x, y); | ||||
|     input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); | ||||
|     m_input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnTouchReleased(int id) { | ||||
|     input_subsystem->GetTouchScreen()->TouchReleased(id); | ||||
|     m_input_subsystem->GetTouchScreen()->TouchReleased(id); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnGamepadButtonEvent(int player_index, int button_id, bool pressed) { | ||||
|     input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed); | ||||
|     m_input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) { | ||||
|     input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y); | ||||
|     m_input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y); | ||||
| } | ||||
|  | ||||
| void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, | ||||
|                                              float gyro_y, float gyro_z, float accel_x, | ||||
|                                              float accel_y, float accel_z) { | ||||
|     input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, | ||||
|                                                          gyro_y, gyro_z, accel_x, accel_y, accel_z); | ||||
|     m_input_subsystem->GetVirtualGamepad()->SetMotionState( | ||||
|         player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); | ||||
| } | ||||
|  | ||||
| EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, | ||||
|                                      ANativeWindow* surface_) | ||||
|     : input_subsystem{input_subsystem_} { | ||||
| EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem, | ||||
|                                      ANativeWindow* surface, | ||||
|                                      std::shared_ptr<Common::DynamicLibrary> driver_library) | ||||
|     : m_input_subsystem{input_subsystem}, m_driver_library{driver_library} { | ||||
|     LOG_INFO(Frontend, "initializing"); | ||||
|  | ||||
|     if (!surface_) { | ||||
|     if (!surface) { | ||||
|         LOG_CRITICAL(Frontend, "surface is nullptr"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     window_width = ANativeWindow_getWidth(surface_); | ||||
|     window_height = ANativeWindow_getHeight(surface_); | ||||
|     m_window_width = ANativeWindow_getWidth(surface); | ||||
|     m_window_height = ANativeWindow_getHeight(surface); | ||||
|  | ||||
|     // Ensures that we emulate with the correct aspect ratio. | ||||
|     UpdateCurrentFramebufferLayout(window_width, window_height); | ||||
|     UpdateCurrentFramebufferLayout(m_window_width, m_window_height); | ||||
|  | ||||
|     host_window = surface_; | ||||
|     m_host_window = surface; | ||||
|     window_info.type = Core::Frontend::WindowSystemType::Android; | ||||
|     window_info.render_surface = reinterpret_cast<void*>(host_window); | ||||
|     window_info.render_surface = reinterpret_cast<void*>(m_host_window); | ||||
|  | ||||
|     input_subsystem->Initialize(); | ||||
|     m_input_subsystem->Initialize(); | ||||
| } | ||||
|  | ||||
| EmuWindow_Android::~EmuWindow_Android() { | ||||
|     input_subsystem->Shutdown(); | ||||
|     m_input_subsystem->Shutdown(); | ||||
| } | ||||
|   | ||||
| @@ -1,21 +1,34 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "core/frontend/graphics_context.h" | ||||
| #include "input_common/main.h" | ||||
|  | ||||
| struct ANativeWindow; | ||||
|  | ||||
| class SharedContext_Android : public Core::Frontend::GraphicsContext { | ||||
| class GraphicsContext_Android final : public Core::Frontend::GraphicsContext { | ||||
| public: | ||||
|     SharedContext_Android() = default; | ||||
|     ~SharedContext_Android() = default; | ||||
|     void MakeCurrent() override {} | ||||
|     void DoneCurrent() override {} | ||||
|     explicit GraphicsContext_Android(std::shared_ptr<Common::DynamicLibrary> driver_library) | ||||
|         : m_driver_library{driver_library} {} | ||||
|  | ||||
|     ~GraphicsContext_Android() = default; | ||||
|  | ||||
|     std::shared_ptr<Common::DynamicLibrary> GetDriverLibrary() override { | ||||
|         return m_driver_library; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     std::shared_ptr<Common::DynamicLibrary> m_driver_library; | ||||
| }; | ||||
|  | ||||
| class EmuWindow_Android : public Core::Frontend::EmuWindow { | ||||
| class EmuWindow_Android final : public Core::Frontend::EmuWindow { | ||||
|  | ||||
| public: | ||||
|     EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, ANativeWindow* surface_); | ||||
|     EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem, ANativeWindow* surface, | ||||
|                       std::shared_ptr<Common::DynamicLibrary> driver_library); | ||||
|  | ||||
|     ~EmuWindow_Android(); | ||||
|  | ||||
|     void OnSurfaceChanged(ANativeWindow* surface); | ||||
| @@ -29,18 +42,20 @@ public: | ||||
|     void OnFrameDisplayed() override {} | ||||
|  | ||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override { | ||||
|         return {std::make_unique<SharedContext_Android>()}; | ||||
|         return {std::make_unique<GraphicsContext_Android>(m_driver_library)}; | ||||
|     } | ||||
|     bool IsShown() const override { | ||||
|         return true; | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|     InputCommon::InputSubsystem* input_subsystem{}; | ||||
|     InputCommon::InputSubsystem* m_input_subsystem{}; | ||||
|  | ||||
|     ANativeWindow* render_window{}; | ||||
|     ANativeWindow* host_window{}; | ||||
|     ANativeWindow* m_render_window{}; | ||||
|     ANativeWindow* m_host_window{}; | ||||
|  | ||||
|     float window_width{}; | ||||
|     float window_height{}; | ||||
|     float m_window_width{}; | ||||
|     float m_window_height{}; | ||||
|  | ||||
|     std::shared_ptr<Common::DynamicLibrary> m_driver_library; | ||||
| }; | ||||
|   | ||||
| @@ -5,11 +5,15 @@ | ||||
| #include <locale> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <dlfcn.h> | ||||
|  | ||||
| #include <adrenotools/driver.h> | ||||
|  | ||||
| #include <android/api-level.h> | ||||
| #include <android/native_window_jni.h> | ||||
|  | ||||
| #include "common/detached_tasks.h" | ||||
| #include "common/dynamic_library.h" | ||||
| #include "common/fs/path_util.h" | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/logging/log.h" | ||||
| @@ -70,6 +74,29 @@ public: | ||||
|         m_native_window = m_native_window_; | ||||
|     } | ||||
|  | ||||
|     void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, | ||||
|                              const std::string& custom_driver_name, | ||||
|                              const std::string& file_redirect_dir) { | ||||
|         void* handle{}; | ||||
|  | ||||
|         // Try to load a custom driver. | ||||
|         if (custom_driver_name.size()) { | ||||
|             handle = adrenotools_open_libvulkan( | ||||
|                 RTLD_NOW, ADRENOTOOLS_DRIVER_CUSTOM | ADRENOTOOLS_DRIVER_FILE_REDIRECT, nullptr, | ||||
|                 hook_lib_dir.c_str(), custom_driver_dir.c_str(), custom_driver_name.c_str(), | ||||
|                 file_redirect_dir.c_str(), nullptr); | ||||
|         } | ||||
|  | ||||
|         // Try to load the system driver. | ||||
|         if (!handle) { | ||||
|             handle = adrenotools_open_libvulkan(RTLD_NOW, ADRENOTOOLS_DRIVER_FILE_REDIRECT, nullptr, | ||||
|                                                 hook_lib_dir.c_str(), nullptr, nullptr, | ||||
|                                                 file_redirect_dir.c_str(), nullptr); | ||||
|         } | ||||
|  | ||||
|         m_vulkan_library = std::make_shared<Common::DynamicLibrary>(handle); | ||||
|     } | ||||
|  | ||||
|     bool IsRunning() const { | ||||
|         std::scoped_lock lock(m_mutex); | ||||
|         return m_is_running; | ||||
| @@ -94,7 +121,8 @@ public: | ||||
|         Config{}; | ||||
|  | ||||
|         // Create the render window. | ||||
|         m_window = std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window); | ||||
|         m_window = std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window, | ||||
|                                                        m_vulkan_library); | ||||
|  | ||||
|         // Initialize system. | ||||
|         m_system.SetShuttingDown(false); | ||||
| @@ -242,6 +270,9 @@ private: | ||||
|     Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized}; | ||||
|     bool m_is_running{}; | ||||
|  | ||||
|     // GPU driver parameters | ||||
|     std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; | ||||
|  | ||||
|     // Synchronization | ||||
|     std::condition_variable_any m_cv; | ||||
|     mutable std::mutex m_perf_stats_mutex; | ||||
| @@ -327,6 +358,14 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNIEnv* env, | ||||
|     Common::FS::SetAppDirectory(GetJString(env, j_directory)); | ||||
| } | ||||
|  | ||||
| void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver( | ||||
|     JNIEnv* env, [[maybe_unused]] jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir, | ||||
|     jstring custom_driver_name, jstring file_redirect_dir) { | ||||
|     EmulationSession::GetInstance().InitializeGpuDriver( | ||||
|         GetJString(env, hook_lib_dir), GetJString(env, custom_driver_dir), | ||||
|         GetJString(env, custom_driver_name), GetJString(env, file_redirect_dir)); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz) { | ||||
|     Core::Crypto::KeyManager::Instance().ReloadKeys(); | ||||
| @@ -363,7 +402,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadButtonEvent([[maybe_unus | ||||
|                                                                     [[maybe_unused]] jint j_device, | ||||
|                                                                     jint j_button, jint action) { | ||||
|     if (EmulationSession::GetInstance().IsRunning()) { | ||||
|         EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device,j_button, action != 0); | ||||
|         EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device, j_button, | ||||
|                                                                       action != 0); | ||||
|     } | ||||
|     return static_cast<jboolean>(true); | ||||
| } | ||||
| @@ -378,26 +418,28 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadJoystickEvent([[maybe_un | ||||
|     return static_cast<jboolean>(true); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent([[maybe_unused]] JNIEnv* env, | ||||
|                                                                     [[maybe_unused]] jclass clazz, jint j_device,jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y, | ||||
|                                                                     jfloat gyro_z, jfloat accel_x, jfloat accel_y, jfloat accel_z){ | ||||
| jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent( | ||||
|     [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint j_device, | ||||
|     jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y, jfloat gyro_z, jfloat accel_x, | ||||
|     jfloat accel_y, jfloat accel_z) { | ||||
|     if (EmulationSession::GetInstance().IsRunning()) { | ||||
|         EmulationSession::GetInstance().Window().OnGamepadMotionEvent(j_device,delta_timestamp, gyro_x, gyro_y,gyro_z,accel_x,accel_y,accel_z); | ||||
|         EmulationSession::GetInstance().Window().OnGamepadMotionEvent( | ||||
|             j_device, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); | ||||
|     } | ||||
|     return static_cast<jboolean>(true); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchPressed([[maybe_unused]] JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz, jint id, jfloat x, | ||||
|                                                           jfloat y) { | ||||
|                                                           [[maybe_unused]] jclass clazz, jint id, | ||||
|                                                           jfloat x, jfloat y) { | ||||
|     if (EmulationSession::GetInstance().IsRunning()) { | ||||
|         EmulationSession::GetInstance().Window().OnTouchPressed(id, x, y); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env, | ||||
|                                                         [[maybe_unused]] jclass clazz, jint id, jfloat x, | ||||
|                                                         jfloat y) { | ||||
|                                                         [[maybe_unused]] jclass clazz, jint id, | ||||
|                                                         jfloat x, jfloat y) { | ||||
|     if (EmulationSession::GetInstance().IsRunning()) { | ||||
|         EmulationSession::GetInstance().Window().OnTouchMoved(id, x, y); | ||||
|     } | ||||
|   | ||||
| @@ -71,6 +71,11 @@ JNIEXPORT void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_SetAppDirectory(JNI | ||||
|                                                                              jclass clazz, | ||||
|                                                                              jstring j_directory); | ||||
|  | ||||
| JNIEXPORT void JNICALL | ||||
| Java_org_yuzu_yuzu_1emu_NativeLibrary_Java_org_yuzu_yuzu_1emu_NativeLibrary_InitializeGpuDriver( | ||||
|     JNIEnv* env, jclass clazz, jstring hook_lib_dir, jstring custom_driver_dir, | ||||
|     jstring custom_driver_name, jstring file_redirect_dir); | ||||
|  | ||||
| JNIEXPORT jboolean JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_ReloadKeys(JNIEnv* env, | ||||
|                                                                             jclass clazz); | ||||
|  | ||||
|   | ||||
| @@ -3,8 +3,9 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <optional> | ||||
| #include <string> | ||||
| #include <memory> | ||||
|  | ||||
| #include "common/dynamic_library.h" | ||||
|  | ||||
| namespace Core::Frontend { | ||||
|  | ||||
| @@ -24,16 +25,8 @@ public: | ||||
|     /// Releases (dunno if this is the "right" word) the context from the caller thread | ||||
|     virtual void DoneCurrent() {} | ||||
|  | ||||
|     /// Parameters used to configure custom drivers (used by Android only) | ||||
|     struct CustomDriverParameters { | ||||
|         std::string hook_lib_dir; | ||||
|         std::string custom_driver_dir; | ||||
|         std::string custom_driver_name; | ||||
|         std::string file_redirect_dir; | ||||
|     }; | ||||
|  | ||||
|     /// Gets custom driver parameters configured by the frontend (used by Android only) | ||||
|     virtual std::optional<CustomDriverParameters> GetCustomDriverParameters() { | ||||
|     /// Gets the GPU driver library (used by Android only) | ||||
|     virtual std::shared_ptr<Common::DynamicLibrary> GetDriverLibrary() { | ||||
|         return {}; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | ||||
|                                Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | ||||
|                                std::unique_ptr<Core::Frontend::GraphicsContext> context_) try | ||||
|     : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), | ||||
|       cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()), | ||||
|       instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | ||||
|       cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), | ||||
|       instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | ||||
|                               Settings::values.renderer_debug.GetValue())), | ||||
|       debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | ||||
|       surface(CreateSurface(instance, render_window.GetWindowInfo())), | ||||
|   | ||||
| @@ -63,7 +63,7 @@ private: | ||||
|     Core::Memory::Memory& cpu_memory; | ||||
|     Tegra::GPU& gpu; | ||||
|  | ||||
|     Common::DynamicLibrary library; | ||||
|     std::shared_ptr<Common::DynamicLibrary> library; | ||||
|     vk::InstanceDispatch dld; | ||||
|  | ||||
|     vk::Instance instance; | ||||
|   | ||||
| @@ -314,10 +314,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | ||||
|     const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; | ||||
|     const bool is_nvidia = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY; | ||||
|     const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK; | ||||
|     const bool is_adreno = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; | ||||
|     const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; | ||||
|     const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; | ||||
|     const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP; | ||||
|  | ||||
|     if ((is_mvk || is_adreno) && !is_suitable) { | ||||
|     if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) { | ||||
|         LOG_WARNING(Render_Vulkan, "Unsuitable driver is MoltenVK, continuing anyway"); | ||||
|     } else if (!is_suitable) { | ||||
|         throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); | ||||
| @@ -362,14 +362,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | ||||
|     CollectToolingInfo(); | ||||
|  | ||||
| #ifdef ANDROID | ||||
|     if (is_adreno) { | ||||
|     if (is_qualcomm) { | ||||
|         must_emulate_scaled_formats = true; | ||||
|  | ||||
|         LOG_WARNING(Render_Vulkan, "Adreno drivers have broken VK_EXT_extended_dynamic_state"); | ||||
|         extensions.extended_dynamic_state = false; | ||||
|         loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | ||||
|  | ||||
|         LOG_WARNING(Render_Vulkan, "Adreno drivers have a slow VK_KHR_push_descriptor implementation"); | ||||
|         LOG_WARNING(Render_Vulkan, | ||||
|                     "Adreno drivers have a slow VK_KHR_push_descriptor implementation"); | ||||
|         extensions.push_descriptor = false; | ||||
|         loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||||
|  | ||||
| @@ -392,6 +393,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; | ||||
|     if (is_arm) { | ||||
|         must_emulate_scaled_formats = true; | ||||
|  | ||||
| @@ -513,7 +515,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | ||||
|         LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); | ||||
|         cant_blit_msaa = true; | ||||
|     } | ||||
|     if (is_intel_anv || is_adreno) { | ||||
|     if (is_intel_anv || is_qualcomm) { | ||||
|         LOG_WARNING(Render_Vulkan, "Driver does not support native BGR format"); | ||||
|         must_emulate_bgr565 = true; | ||||
|     } | ||||
|   | ||||
| @@ -10,29 +10,35 @@ | ||||
|  | ||||
| namespace Vulkan { | ||||
|  | ||||
| Common::DynamicLibrary OpenLibrary() { | ||||
| std::shared_ptr<Common::DynamicLibrary> OpenLibrary( | ||||
|     [[maybe_unused]] Core::Frontend::GraphicsContext* context) { | ||||
|     LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); | ||||
|     Common::DynamicLibrary library; | ||||
| #ifdef ANDROID | ||||
|     // Android manages its Vulkan driver from the frontend. | ||||
|     return context->GetDriverLibrary(); | ||||
| #else | ||||
|     auto library = std::make_shared<Common::DynamicLibrary>(); | ||||
| #ifdef __APPLE__ | ||||
|     // Check if a path to a specific Vulkan library has been specified. | ||||
|     char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); | ||||
|     if (!libvulkan_env || !library.Open(libvulkan_env)) { | ||||
|     if (!libvulkan_env || !library->Open(libvulkan_env)) { | ||||
|         // Use the libvulkan.dylib from the application bundle. | ||||
|         const auto filename = | ||||
|             Common::FS::GetBundleDirectory() / "Contents/Frameworks/libvulkan.dylib"; | ||||
|         void(library.Open(Common::FS::PathToUTF8String(filename).c_str())); | ||||
|         void(library->Open(Common::FS::PathToUTF8String(filename).c_str())); | ||||
|     } | ||||
| #else | ||||
|     std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); | ||||
|     LOG_DEBUG(Render_Vulkan, "Trying Vulkan library: {}", filename); | ||||
|     if (!library.Open(filename.c_str())) { | ||||
|     if (!library->Open(filename.c_str())) { | ||||
|         // Android devices may not have libvulkan.so.1, only libvulkan.so. | ||||
|         filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); | ||||
|         LOG_DEBUG(Render_Vulkan, "Trying Vulkan library (second attempt): {}", filename); | ||||
|         void(library.Open(filename.c_str())); | ||||
|         void(library->Open(filename.c_str())); | ||||
|     } | ||||
| #endif | ||||
|     return library; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| } // namespace Vulkan | ||||
|   | ||||
| @@ -3,10 +3,14 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "common/dynamic_library.h" | ||||
| #include "core/frontend/graphics_context.h" | ||||
|  | ||||
| namespace Vulkan { | ||||
|  | ||||
| Common::DynamicLibrary OpenLibrary(); | ||||
| std::shared_ptr<Common::DynamicLibrary> OpenLibrary( | ||||
|     [[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr); | ||||
|  | ||||
| } // namespace Vulkan | ||||
|   | ||||
| @@ -515,8 +515,8 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { | ||||
|     auto wsi = QtCommon::GetWindowSystemInfo(window); | ||||
|  | ||||
|     vk::InstanceDispatch dld; | ||||
|     const Common::DynamicLibrary library = OpenLibrary(); | ||||
|     const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type); | ||||
|     const auto library = OpenLibrary(); | ||||
|     const vk::Instance instance = CreateInstance(*library, dld, VK_API_VERSION_1_1, wsi.type); | ||||
|     const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); | ||||
|     vk::SurfaceKHR surface = CreateSurface(instance, wsi); | ||||
|  | ||||
|   | ||||
| @@ -25,9 +25,9 @@ void CheckVulkan() { | ||||
|     // Just start the Vulkan loader, this will crash if something is wrong | ||||
|     try { | ||||
|         Vulkan::vk::InstanceDispatch dld; | ||||
|         const Common::DynamicLibrary library = Vulkan::OpenLibrary(); | ||||
|         const auto library = Vulkan::OpenLibrary(); | ||||
|         const Vulkan::vk::Instance instance = | ||||
|             Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1); | ||||
|             Vulkan::CreateInstance(*library, dld, VK_API_VERSION_1_1); | ||||
|  | ||||
|     } catch (const Vulkan::vk::Exception& exception) { | ||||
|         fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user