From 4c38220a644f8292f4915eaabb2f80d3d0badab0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 18 Feb 2023 23:42:07 -0800 Subject: android: native: Add support for custom Vulkan driver loading. --- .../main/java/org/yuzu/yuzu_emu/NativeLibrary.java | 2 + src/android/app/src/main/jni/CMakeLists.txt | 2 +- .../app/src/main/jni/emu_window/emu_window.cpp | 39 ++++++------- .../app/src/main/jni/emu_window/emu_window.h | 41 +++++++++----- src/android/app/src/main/jni/native.cpp | 64 ++++++++++++++++++---- src/android/app/src/main/jni/native.h | 5 ++ 6 files changed, 109 insertions(+), 44 deletions(-) (limited to 'src/android/app') diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java index a0f6c1f7b..e56196310 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java @@ -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. diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index e5c9d57f2..f80c166f4 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -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) diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp index 2beba6804..ad17cf129 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.cpp +++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp @@ -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 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(host_window); + window_info.render_surface = reinterpret_cast(m_host_window); - input_subsystem->Initialize(); + m_input_subsystem->Initialize(); } EmuWindow_Android::~EmuWindow_Android() { - input_subsystem->Shutdown(); + m_input_subsystem->Shutdown(); } diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h index 544924caa..1c1edf62c 100644 --- a/src/android/app/src/main/jni/emu_window/emu_window.h +++ b/src/android/app/src/main/jni/emu_window/emu_window.h @@ -1,21 +1,34 @@ #pragma once +#include + #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 driver_library) + : m_driver_library{driver_library} {} + + ~GraphicsContext_Android() = default; + + std::shared_ptr GetDriverLibrary() override { + return m_driver_library; + } + +private: + std::shared_ptr 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 driver_library); + ~EmuWindow_Android(); void OnSurfaceChanged(ANativeWindow* surface); @@ -29,18 +42,20 @@ public: void OnFrameDisplayed() override {} std::unique_ptr CreateSharedContext() const override { - return {std::make_unique()}; + return {std::make_unique(m_driver_library)}; } bool IsShown() const override { return true; }; private: - InputCommon::InputSubsystem* input_subsystem{}; + InputCommon::InputSubsystem* m_input_subsystem{}; + + ANativeWindow* m_render_window{}; + ANativeWindow* m_host_window{}; - ANativeWindow* render_window{}; - ANativeWindow* host_window{}; + float m_window_width{}; + float m_window_height{}; - float window_width{}; - float window_height{}; + std::shared_ptr m_driver_library; }; diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 0a2a65721..a8f3d135e 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -5,11 +5,15 @@ #include #include #include +#include + +#include #include #include #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(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(&m_input_subsystem, m_native_window); + m_window = std::make_unique(&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 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(true); } @@ -373,31 +413,33 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadJoystickEvent([[maybe_un jint j_device, jint stick_id, jfloat x, jfloat y) { if (EmulationSession::GetInstance().IsRunning()) { - EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device,stick_id, x, y); + EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device, stick_id, x, y); } return static_cast(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(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); } diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index bbc783aa8..f799560e4 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -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); -- cgit v1.2.3