diff options
| author | 2023-05-03 21:54:31 -0700 | |
|---|---|---|
| committer | 2023-06-03 00:05:59 -0700 | |
| commit | 117bc2ae6c9683fd4530cfddb33b4ffc9419cff7 (patch) | |
| tree | abe55ef4689045d68e88938078544fbdf0356c46 | |
| parent | android: Game data cache (diff) | |
| download | yuzu-117bc2ae6c9683fd4530cfddb33b4ffc9419cff7.tar.gz yuzu-117bc2ae6c9683fd4530cfddb33b4ffc9419cff7.tar.xz yuzu-117bc2ae6c9683fd4530cfddb33b4ffc9419cff7.zip | |
android: vulkan: Recreate surface after suspension & adapt to async. presentation.
8 files changed, 39 insertions, 26 deletions
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index 785133057..7a83fea42 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() { | |||
| 217 | ReadSetting("Renderer", Settings::values.accelerate_astc); | 217 | ReadSetting("Renderer", Settings::values.accelerate_astc); |
| 218 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | 218 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |
| 219 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | 219 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); |
| 220 | ReadSetting("Renderer", Settings::values.async_presentation); | ||
| 220 | 221 | ||
| 221 | // Use GPU accuracy normal by default on Android | 222 | // Use GPU accuracy normal by default on Android |
| 222 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger( | 223 | Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger( |
| @@ -230,10 +231,6 @@ void Config::ReadValues() { | |||
| 230 | Settings::values.renderer_force_max_clock = | 231 | Settings::values.renderer_force_max_clock = |
| 231 | config->GetBoolean("Renderer", "force_max_clock", true); | 232 | config->GetBoolean("Renderer", "force_max_clock", true); |
| 232 | 233 | ||
| 233 | // Enable asynchronous presentation by default on Android | ||
| 234 | Settings::values.async_presentation = | ||
| 235 | config->GetBoolean("Renderer", "async_presentation", true); | ||
| 236 | |||
| 237 | // Audio | 234 | // Audio |
| 238 | ReadSetting("Audio", Settings::values.sink_id); | 235 | ReadSetting("Audio", Settings::values.sink_id); |
| 239 | ReadSetting("Audio", Settings::values.audio_output_device_id); | 236 | 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 2fdb68823..926bb30e8 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 @@ | |||
| 8 | #include "jni/emu_window/emu_window.h" | 8 | #include "jni/emu_window/emu_window.h" |
| 9 | 9 | ||
| 10 | void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | 10 | void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { |
| 11 | m_render_window = surface; | 11 | window_info.render_surface = reinterpret_cast<void*>(surface); |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { | 14 | void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { |
| @@ -37,7 +37,7 @@ void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timesta | |||
| 37 | float gyro_y, float gyro_z, float accel_x, | 37 | float gyro_y, float gyro_z, float accel_x, |
| 38 | float accel_y, float accel_z) { | 38 | float accel_y, float accel_z) { |
| 39 | m_input_subsystem->GetVirtualGamepad()->SetMotionState( | 39 | m_input_subsystem->GetVirtualGamepad()->SetMotionState( |
| 40 | player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); | 40 | player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | void EmuWindow_Android::OnReadNfcTag(std::span<u8> data) { | 43 | void EmuWindow_Android::OnReadNfcTag(std::span<u8> data) { |
| @@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste | |||
| 65 | // Ensures that we emulate with the correct aspect ratio. | 65 | // Ensures that we emulate with the correct aspect ratio. |
| 66 | UpdateCurrentFramebufferLayout(m_window_width, m_window_height); | 66 | UpdateCurrentFramebufferLayout(m_window_width, m_window_height); |
| 67 | 67 | ||
| 68 | m_host_window = surface; | ||
| 69 | window_info.type = Core::Frontend::WindowSystemType::Android; | 68 | window_info.type = Core::Frontend::WindowSystemType::Android; |
| 70 | window_info.render_surface = reinterpret_cast<void*>(m_host_window); | 69 | window_info.render_surface = reinterpret_cast<void*>(surface); |
| 71 | 70 | ||
| 72 | m_input_subsystem->Initialize(); | 71 | m_input_subsystem->Initialize(); |
| 73 | } | 72 | } |
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 2a0a72077..36d46eb51 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: | |||
| 54 | private: | 54 | private: |
| 55 | InputCommon::InputSubsystem* m_input_subsystem{}; | 55 | InputCommon::InputSubsystem* m_input_subsystem{}; |
| 56 | 56 | ||
| 57 | ANativeWindow* m_render_window{}; | ||
| 58 | ANativeWindow* m_host_window{}; | ||
| 59 | |||
| 60 | float m_window_width{}; | 57 | float m_window_width{}; |
| 61 | float m_window_height{}; | 58 | float m_window_height{}; |
| 62 | 59 | ||
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 30dc69f13..77128c6e2 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_, | |||
| 93 | state_tracker(), scheduler(device, state_tracker), | 93 | state_tracker(), scheduler(device, state_tracker), |
| 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |
| 95 | render_window.GetFramebufferLayout().height, false), | 95 | render_window.GetFramebufferLayout().height, false), |
| 96 | present_manager(render_window, device, memory_allocator, scheduler, swapchain), | 96 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, |
| 97 | surface), | ||
| 97 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, | 98 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, |
| 98 | scheduler, screen_info), | 99 | scheduler, screen_info), |
| 99 | rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, | 100 | 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 c49583013..77832720d 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 @@ | |||
| 4 | #include "common/microprofile.h" | 4 | #include "common/microprofile.h" |
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "common/thread.h" | 6 | #include "common/thread.h" |
| 7 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "video_core/renderer_vulkan/vk_present_manager.h" | 8 | #include "video_core/renderer_vulkan/vk_present_manager.h" |
| 8 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 9 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 9 | #include "video_core/renderer_vulkan/vk_swapchain.h" | 10 | #include "video_core/renderer_vulkan/vk_swapchain.h" |
| 10 | #include "video_core/vulkan_common/vulkan_device.h" | 11 | #include "video_core/vulkan_common/vulkan_device.h" |
| 12 | #include "video_core/vulkan_common/vulkan_surface.h" | ||
| 11 | 13 | ||
| 12 | namespace Vulkan { | 14 | namespace Vulkan { |
| 13 | 15 | ||
| @@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form | |||
| 92 | 94 | ||
| 93 | } // Anonymous namespace | 95 | } // Anonymous namespace |
| 94 | 96 | ||
| 95 | PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_, | 97 | PresentManager::PresentManager(const vk::Instance& instance_, |
| 98 | Core::Frontend::EmuWindow& render_window_, const Device& device_, | ||
| 96 | MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | 99 | MemoryAllocator& memory_allocator_, Scheduler& scheduler_, |
| 97 | Swapchain& swapchain_) | 100 | Swapchain& swapchain_, vk::SurfaceKHR& surface_) |
| 98 | : render_window{render_window_}, device{device_}, | 101 | : instance{instance_}, render_window{render_window_}, device{device_}, |
| 99 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, | 102 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, |
| 100 | blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}, | 103 | surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), |
| 104 | swapchain.GetImageViewFormat())}, | ||
| 101 | use_present_thread{Settings::values.async_presentation.GetValue()}, | 105 | use_present_thread{Settings::values.async_presentation.GetValue()}, |
| 102 | image_count{swapchain.GetImageCount()} { | 106 | image_count{swapchain.GetImageCount()}, last_render_surface{ |
| 107 | render_window_.GetWindowInfo().render_surface} { | ||
| 103 | 108 | ||
| 104 | auto& dld = device.GetLogical(); | 109 | auto& dld = device.GetLogical(); |
| 105 | cmdpool = dld.CreateCommandPool({ | 110 | cmdpool = dld.CreateCommandPool({ |
| @@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) { | |||
| 290 | MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); | 295 | MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); |
| 291 | 296 | ||
| 292 | const auto recreate_swapchain = [&] { | 297 | const auto recreate_swapchain = [&] { |
| 293 | swapchain.Create(frame->width, frame->height, frame->is_srgb); | 298 | swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); |
| 294 | image_count = swapchain.GetImageCount(); | 299 | image_count = swapchain.GetImageCount(); |
| 295 | }; | 300 | }; |
| 296 | 301 | ||
| 302 | #ifdef ANDROID | ||
| 303 | // If the frontend recreated the surface, recreate the renderer surface and swapchain. | ||
| 304 | if (last_render_surface != render_window.GetWindowInfo().render_surface) { | ||
| 305 | last_render_surface = render_window.GetWindowInfo().render_surface; | ||
| 306 | surface = CreateSurface(instance, render_window.GetWindowInfo()); | ||
| 307 | recreate_swapchain(); | ||
| 308 | } | ||
| 309 | #endif | ||
| 310 | |||
| 297 | // If the size or colorspace of the incoming frames has changed, recreate the swapchain | 311 | // If the size or colorspace of the incoming frames has changed, recreate the swapchain |
| 298 | // to account for that. | 312 | // to account for that. |
| 299 | const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); | 313 | const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); |
| @@ -454,4 +468,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) { | |||
| 454 | swapchain.Present(render_semaphore); | 468 | swapchain.Present(render_semaphore); |
| 455 | } | 469 | } |
| 456 | 470 | ||
| 457 | } // namespace Vulkan | 471 | } // 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 420a775e2..3cbfce4ed 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 { | |||
| 37 | 37 | ||
| 38 | class PresentManager { | 38 | class PresentManager { |
| 39 | public: | 39 | public: |
| 40 | PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device, | 40 | PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, |
| 41 | MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain); | 41 | const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, |
| 42 | Swapchain& swapchain, vk::SurfaceKHR& surface); | ||
| 42 | ~PresentManager(); | 43 | ~PresentManager(); |
| 43 | 44 | ||
| 44 | /// Returns the last used presentation frame | 45 | /// Returns the last used presentation frame |
| @@ -60,11 +61,13 @@ private: | |||
| 60 | void CopyToSwapchain(Frame* frame); | 61 | void CopyToSwapchain(Frame* frame); |
| 61 | 62 | ||
| 62 | private: | 63 | private: |
| 64 | const vk::Instance& instance; | ||
| 63 | Core::Frontend::EmuWindow& render_window; | 65 | Core::Frontend::EmuWindow& render_window; |
| 64 | const Device& device; | 66 | const Device& device; |
| 65 | MemoryAllocator& memory_allocator; | 67 | MemoryAllocator& memory_allocator; |
| 66 | Scheduler& scheduler; | 68 | Scheduler& scheduler; |
| 67 | Swapchain& swapchain; | 69 | Swapchain& swapchain; |
| 70 | vk::SurfaceKHR& surface; | ||
| 68 | vk::CommandPool cmdpool; | 71 | vk::CommandPool cmdpool; |
| 69 | std::vector<Frame> frames; | 72 | std::vector<Frame> frames; |
| 70 | std::queue<Frame*> present_queue; | 73 | std::queue<Frame*> present_queue; |
| @@ -77,7 +80,8 @@ private: | |||
| 77 | std::jthread present_thread; | 80 | std::jthread present_thread; |
| 78 | bool blit_supported; | 81 | bool blit_supported; |
| 79 | bool use_present_thread; | 82 | bool use_present_thread; |
| 80 | std::size_t image_count; | 83 | std::size_t image_count{}; |
| 84 | void* last_render_surface{}; | ||
| 81 | }; | 85 | }; |
| 82 | 86 | ||
| 83 | } // namespace Vulkan | 87 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index e43a993f9..afcf34fba 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 | |||
| 107 | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, | 107 | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, |
| 108 | u32 width_, u32 height_, bool srgb) | 108 | u32 width_, u32 height_, bool srgb) |
| 109 | : surface{surface_}, device{device_}, scheduler{scheduler_} { | 109 | : surface{surface_}, device{device_}, scheduler{scheduler_} { |
| 110 | Create(width_, height_, srgb); | 110 | Create(surface_, width_, height_, srgb); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | Swapchain::~Swapchain() = default; | 113 | Swapchain::~Swapchain() = default; |
| 114 | 114 | ||
| 115 | void Swapchain::Create(u32 width_, u32 height_, bool srgb) { | 115 | void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { |
| 116 | is_outdated = false; | 116 | is_outdated = false; |
| 117 | is_suboptimal = false; | 117 | is_suboptimal = false; |
| 118 | width = width_; | 118 | width = width_; |
| 119 | height = height_; | 119 | height = height_; |
| 120 | surface = surface_; | ||
| 120 | 121 | ||
| 121 | const auto physical_device = device.GetPhysical(); | 122 | const auto physical_device = device.GetPhysical(); |
| 122 | const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; | 123 | 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 bf1ea7254..b8a1465a6 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 24 | ~Swapchain(); | 24 | ~Swapchain(); |
| 25 | 25 | ||
| 26 | /// Creates (or recreates) the swapchain with a given size. | 26 | /// Creates (or recreates) the swapchain with a given size. |
| 27 | void Create(u32 width, u32 height, bool srgb); | 27 | void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb); |
| 28 | 28 | ||
| 29 | /// Acquires the next image in the swapchain, waits as needed. | 29 | /// Acquires the next image in the swapchain, waits as needed. |
| 30 | bool AcquireNextImage(); | 30 | bool AcquireNextImage(); |
| @@ -118,7 +118,7 @@ private: | |||
| 118 | 118 | ||
| 119 | bool NeedsPresentModeUpdate() const; | 119 | bool NeedsPresentModeUpdate() const; |
| 120 | 120 | ||
| 121 | const VkSurfaceKHR surface; | 121 | VkSurfaceKHR surface; |
| 122 | const Device& device; | 122 | const Device& device; |
| 123 | Scheduler& scheduler; | 123 | Scheduler& scheduler; |
| 124 | 124 | ||