From 56600190e4dc937f25f601ae0f40cd8dcf3bf260 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 18 Feb 2023 23:31:39 -0800 Subject: core: frontend: Refactor GraphicsContext to its own module. --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/renderer_vulkan/renderer_vulkan.cpp') diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 8e31eba34a..fbcf4c1d36 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -16,7 +16,7 @@ #include "common/settings.h" #include "common/telemetry.h" #include "core/core_timing.h" -#include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" #include "core/telemetry_session.h" #include "video_core/gpu.h" #include "video_core/renderer_vulkan/renderer_vulkan.h" -- cgit v1.2.3 From 74e76421e64a21e1eef14c614b32a97bbab62db2 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 ++ src/core/frontend/graphics_context.h | 17 ++---- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 4 +- src/video_core/renderer_vulkan/renderer_vulkan.h | 2 +- src/video_core/vulkan_common/vulkan_device.cpp | 14 +++-- src/video_core/vulkan_common/vulkan_library.cpp | 18 ++++-- src/video_core/vulkan_common/vulkan_library.h | 6 +- src/yuzu/configuration/configure_graphics.cpp | 4 +- src/yuzu/startup_checks.cpp | 4 +- 14 files changed, 146 insertions(+), 76 deletions(-) (limited to 'src/video_core/renderer_vulkan/renderer_vulkan.cpp') 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 a0f6c1f7bc..e56196310d 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 e5c9d57f29..f80c166f4c 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 2beba6804c..ad17cf1296 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 544924caa1..1c1edf62c6 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 0a2a657216..a8f3d135e0 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 bbc783aa87..f799560e47 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); diff --git a/src/core/frontend/graphics_context.h b/src/core/frontend/graphics_context.h index 064b19a965..7554c15833 100644 --- a/src/core/frontend/graphics_context.h +++ b/src/core/frontend/graphics_context.h @@ -3,8 +3,9 @@ #pragma once -#include -#include +#include + +#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 GetCustomDriverParameters() { + /// Gets the GPU driver library (used by Android only) + virtual std::shared_ptr GetDriverLibrary() { return {}; } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index fbcf4c1d36..30dc69f130 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, std::unique_ptr 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())), diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index f44367cb25..3c63a2004a 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -63,7 +63,7 @@ private: Core::Memory::Memory& cpu_memory; Tegra::GPU& gpu; - Common::DynamicLibrary library; + std::shared_ptr library; vk::InstanceDispatch dld; vk::Instance instance; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 63e1c7d63d..40cdf2fde0 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -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; } diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp index 4eb3913ee1..9a7d369f32 100644 --- a/src/video_core/vulkan_common/vulkan_library.cpp +++ b/src/video_core/vulkan_common/vulkan_library.cpp @@ -10,29 +10,35 @@ namespace Vulkan { -Common::DynamicLibrary OpenLibrary() { +std::shared_ptr 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(); #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 diff --git a/src/video_core/vulkan_common/vulkan_library.h b/src/video_core/vulkan_common/vulkan_library.h index 364ca979b6..e1734525ee 100644 --- a/src/video_core/vulkan_common/vulkan_library.h +++ b/src/video_core/vulkan_common/vulkan_library.h @@ -3,10 +3,14 @@ #pragma once +#include + #include "common/dynamic_library.h" +#include "core/frontend/graphics_context.h" namespace Vulkan { -Common::DynamicLibrary OpenLibrary(); +std::shared_ptr OpenLibrary( + [[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr); } // namespace Vulkan diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index f316b598cc..4315852160 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -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 physical_devices = instance.EnumeratePhysicalDevices(); vk::SurfaceKHR surface = CreateSurface(instance, wsi); diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index 5e1f763392..6eefc94ed0 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp @@ -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()); -- cgit v1.2.3 From 2650faea9d076cd246bda0239f9c2bae76f96a4d Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 3 May 2023 21:54:31 -0700 Subject: android: vulkan: Recreate surface after suspension & adapt to async. presentation. --- src/android/app/src/main/jni/config.cpp | 5 +--- .../app/src/main/jni/emu_window/emu_window.cpp | 7 +++--- .../app/src/main/jni/emu_window/emu_window.h | 3 --- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 3 ++- .../renderer_vulkan/vk_present_manager.cpp | 28 ++++++++++++++++------ .../renderer_vulkan/vk_present_manager.h | 10 +++++--- src/video_core/renderer_vulkan/vk_swapchain.cpp | 5 ++-- src/video_core/renderer_vulkan/vk_swapchain.h | 4 ++-- 8 files changed, 39 insertions(+), 26 deletions(-) (limited to 'src/video_core/renderer_vulkan/renderer_vulkan.cpp') diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 7851330577..7a83fea42e 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -217,6 +217,7 @@ void Config::ReadValues() { ReadSetting("Renderer", Settings::values.accelerate_astc); ReadSetting("Renderer", Settings::values.use_fast_gpu_time); ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); + ReadSetting("Renderer", Settings::values.async_presentation); // Use GPU accuracy normal by default on Android Settings::values.gpu_accuracy = static_cast(config->GetInteger( @@ -230,10 +231,6 @@ void Config::ReadValues() { Settings::values.renderer_force_max_clock = config->GetBoolean("Renderer", "force_max_clock", true); - // Enable asynchronous presentation by default on Android - Settings::values.async_presentation = - config->GetBoolean("Renderer", "async_presentation", true); - // Audio ReadSetting("Audio", Settings::values.sink_id); ReadSetting("Audio", Settings::values.audio_output_device_id); 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 2fdb688236..926bb30e85 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 @@ -8,7 +8,7 @@ #include "jni/emu_window/emu_window.h" void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { - m_render_window = surface; + window_info.render_surface = reinterpret_cast(surface); } void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { @@ -37,7 +37,7 @@ void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timesta float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z) { m_input_subsystem->GetVirtualGamepad()->SetMotionState( - player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); + player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); } void EmuWindow_Android::OnReadNfcTag(std::span data) { @@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste // Ensures that we emulate with the correct aspect ratio. UpdateCurrentFramebufferLayout(m_window_width, m_window_height); - m_host_window = surface; window_info.type = Core::Frontend::WindowSystemType::Android; - window_info.render_surface = reinterpret_cast(m_host_window); + window_info.render_surface = reinterpret_cast(surface); m_input_subsystem->Initialize(); } 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 2a0a720772..36d46eb510 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 @@ -54,9 +54,6 @@ public: private: InputCommon::InputSubsystem* m_input_subsystem{}; - ANativeWindow* m_render_window{}; - ANativeWindow* m_host_window{}; - float m_window_width{}; float m_window_height{}; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 30dc69f130..77128c6e29 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, state_tracker(), scheduler(device, state_tracker), swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, render_window.GetFramebufferLayout().height, false), - present_manager(render_window, device, memory_allocator, scheduler, swapchain), + present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, + surface), blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, scheduler, screen_info), rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index c495830136..77832720df 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -4,10 +4,12 @@ #include "common/microprofile.h" #include "common/settings.h" #include "common/thread.h" +#include "core/frontend/emu_window.h" #include "video_core/renderer_vulkan/vk_present_manager.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_swapchain.h" #include "video_core/vulkan_common/vulkan_device.h" +#include "video_core/vulkan_common/vulkan_surface.h" namespace Vulkan { @@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form } // Anonymous namespace -PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_, +PresentManager::PresentManager(const vk::Instance& instance_, + Core::Frontend::EmuWindow& render_window_, const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, - Swapchain& swapchain_) - : render_window{render_window_}, device{device_}, + Swapchain& swapchain_, vk::SurfaceKHR& surface_) + : instance{instance_}, render_window{render_window_}, device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, - blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}, + surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), + swapchain.GetImageViewFormat())}, use_present_thread{Settings::values.async_presentation.GetValue()}, - image_count{swapchain.GetImageCount()} { + image_count{swapchain.GetImageCount()}, last_render_surface{ + render_window_.GetWindowInfo().render_surface} { auto& dld = device.GetLogical(); cmdpool = dld.CreateCommandPool({ @@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) { MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); const auto recreate_swapchain = [&] { - swapchain.Create(frame->width, frame->height, frame->is_srgb); + swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); image_count = swapchain.GetImageCount(); }; +#ifdef ANDROID + // If the frontend recreated the surface, recreate the renderer surface and swapchain. + if (last_render_surface != render_window.GetWindowInfo().render_surface) { + last_render_surface = render_window.GetWindowInfo().render_surface; + surface = CreateSurface(instance, render_window.GetWindowInfo()); + recreate_swapchain(); + } +#endif + // If the size or colorspace of the incoming frames has changed, recreate the swapchain // to account for that. const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); @@ -454,4 +468,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) { swapchain.Present(render_semaphore); } -} // namespace Vulkan +} // namespace Vulkan \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 420a775e2a..3cbfce4edc 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h @@ -37,8 +37,9 @@ struct Frame { class PresentManager { public: - PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device, - MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain); + PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, + const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, + Swapchain& swapchain, vk::SurfaceKHR& surface); ~PresentManager(); /// Returns the last used presentation frame @@ -60,11 +61,13 @@ private: void CopyToSwapchain(Frame* frame); private: + const vk::Instance& instance; Core::Frontend::EmuWindow& render_window; const Device& device; MemoryAllocator& memory_allocator; Scheduler& scheduler; Swapchain& swapchain; + vk::SurfaceKHR& surface; vk::CommandPool cmdpool; std::vector frames; std::queue present_queue; @@ -77,7 +80,8 @@ private: std::jthread present_thread; bool blit_supported; bool use_present_thread; - std::size_t image_count; + std::size_t image_count{}; + void* last_render_surface{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index e43a993f91..afcf34fba4 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width_, u32 height_, bool srgb) : surface{surface_}, device{device_}, scheduler{scheduler_} { - Create(width_, height_, srgb); + Create(surface_, width_, height_, srgb); } Swapchain::~Swapchain() = default; -void Swapchain::Create(u32 width_, u32 height_, bool srgb) { +void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { is_outdated = false; is_suboptimal = false; width = width_; height = height_; + surface = surface_; const auto physical_device = device.GetPhysical(); const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index bf1ea7254c..b8a1465a6f 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -24,7 +24,7 @@ public: ~Swapchain(); /// Creates (or recreates) the swapchain with a given size. - void Create(u32 width, u32 height, bool srgb); + void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb); /// Acquires the next image in the swapchain, waits as needed. bool AcquireNextImage(); @@ -118,7 +118,7 @@ private: bool NeedsPresentModeUpdate() const; - const VkSurfaceKHR surface; + VkSurfaceKHR surface; const Device& device; Scheduler& scheduler; -- cgit v1.2.3