android: vulkan: Recreate surface after suspension & adapt to async. presentation.
This commit is contained in:
		| @@ -217,6 +217,7 @@ void Config::ReadValues() { | |||||||
|     ReadSetting("Renderer", Settings::values.accelerate_astc); |     ReadSetting("Renderer", Settings::values.accelerate_astc); | ||||||
|     ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |     ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | ||||||
|     ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); |     ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | ||||||
|  |     ReadSetting("Renderer", Settings::values.async_presentation); | ||||||
|  |  | ||||||
|     // Use GPU accuracy normal by default on Android |     // Use GPU accuracy normal by default on Android | ||||||
|     Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger( |     Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger( | ||||||
| @@ -230,10 +231,6 @@ void Config::ReadValues() { | |||||||
|     Settings::values.renderer_force_max_clock = |     Settings::values.renderer_force_max_clock = | ||||||
|         config->GetBoolean("Renderer", "force_max_clock", true); |         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 |     // Audio | ||||||
|     ReadSetting("Audio", Settings::values.sink_id); |     ReadSetting("Audio", Settings::values.sink_id); | ||||||
|     ReadSetting("Audio", Settings::values.audio_output_device_id); |     ReadSetting("Audio", Settings::values.audio_output_device_id); | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
| #include "jni/emu_window/emu_window.h" | #include "jni/emu_window/emu_window.h" | ||||||
|  |  | ||||||
| void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { | ||||||
|     m_render_window = surface; |     window_info.render_surface = reinterpret_cast<void*>(surface); | ||||||
| } | } | ||||||
|  |  | ||||||
| void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { | void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { | ||||||
| @@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste | |||||||
|     // Ensures that we emulate with the correct aspect ratio. |     // Ensures that we emulate with the correct aspect ratio. | ||||||
|     UpdateCurrentFramebufferLayout(m_window_width, m_window_height); |     UpdateCurrentFramebufferLayout(m_window_width, m_window_height); | ||||||
|  |  | ||||||
|     m_host_window = surface; |  | ||||||
|     window_info.type = Core::Frontend::WindowSystemType::Android; |     window_info.type = Core::Frontend::WindowSystemType::Android; | ||||||
|     window_info.render_surface = reinterpret_cast<void*>(m_host_window); |     window_info.render_surface = reinterpret_cast<void*>(surface); | ||||||
|  |  | ||||||
|     m_input_subsystem->Initialize(); |     m_input_subsystem->Initialize(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -54,9 +54,6 @@ public: | |||||||
| private: | private: | ||||||
|     InputCommon::InputSubsystem* m_input_subsystem{}; |     InputCommon::InputSubsystem* m_input_subsystem{}; | ||||||
|  |  | ||||||
|     ANativeWindow* m_render_window{}; |  | ||||||
|     ANativeWindow* m_host_window{}; |  | ||||||
|  |  | ||||||
|     float m_window_width{}; |     float m_window_width{}; | ||||||
|     float m_window_height{}; |     float m_window_height{}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||||||
|       state_tracker(), scheduler(device, state_tracker), |       state_tracker(), scheduler(device, state_tracker), | ||||||
|       swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |       swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | ||||||
|                 render_window.GetFramebufferLayout().height, false), |                 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, |       blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, | ||||||
|                   scheduler, screen_info), |                   scheduler, screen_info), | ||||||
|       rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, |       rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, | ||||||
|   | |||||||
| @@ -4,10 +4,12 @@ | |||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/settings.h" | #include "common/settings.h" | ||||||
| #include "common/thread.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_present_manager.h" | ||||||
| #include "video_core/renderer_vulkan/vk_scheduler.h" | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||||||
| #include "video_core/renderer_vulkan/vk_swapchain.h" | #include "video_core/renderer_vulkan/vk_swapchain.h" | ||||||
| #include "video_core/vulkan_common/vulkan_device.h" | #include "video_core/vulkan_common/vulkan_device.h" | ||||||
|  | #include "video_core/vulkan_common/vulkan_surface.h" | ||||||
|  |  | ||||||
| namespace Vulkan { | namespace Vulkan { | ||||||
|  |  | ||||||
| @@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form | |||||||
|  |  | ||||||
| } // Anonymous namespace | } // 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_, |                                MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | ||||||
|                                Swapchain& swapchain_) |                                Swapchain& swapchain_, vk::SurfaceKHR& surface_) | ||||||
|     : render_window{render_window_}, device{device_}, |     : instance{instance_}, render_window{render_window_}, device{device_}, | ||||||
|       memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, |       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()}, |       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(); |     auto& dld = device.GetLogical(); | ||||||
|     cmdpool = dld.CreateCommandPool({ |     cmdpool = dld.CreateCommandPool({ | ||||||
| @@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) { | |||||||
|     MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); |     MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); | ||||||
|  |  | ||||||
|     const auto recreate_swapchain = [&] { |     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(); |         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 |     // If the size or colorspace of the incoming frames has changed, recreate the swapchain | ||||||
|     // to account for that. |     // to account for that. | ||||||
|     const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); |     const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); | ||||||
|   | |||||||
| @@ -37,8 +37,9 @@ struct Frame { | |||||||
|  |  | ||||||
| class PresentManager { | class PresentManager { | ||||||
| public: | public: | ||||||
|     PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device, |     PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, | ||||||
|                    MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain); |                    const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, | ||||||
|  |                    Swapchain& swapchain, vk::SurfaceKHR& surface); | ||||||
|     ~PresentManager(); |     ~PresentManager(); | ||||||
|  |  | ||||||
|     /// Returns the last used presentation frame |     /// Returns the last used presentation frame | ||||||
| @@ -60,11 +61,13 @@ private: | |||||||
|     void CopyToSwapchain(Frame* frame); |     void CopyToSwapchain(Frame* frame); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     const vk::Instance& instance; | ||||||
|     Core::Frontend::EmuWindow& render_window; |     Core::Frontend::EmuWindow& render_window; | ||||||
|     const Device& device; |     const Device& device; | ||||||
|     MemoryAllocator& memory_allocator; |     MemoryAllocator& memory_allocator; | ||||||
|     Scheduler& scheduler; |     Scheduler& scheduler; | ||||||
|     Swapchain& swapchain; |     Swapchain& swapchain; | ||||||
|  |     vk::SurfaceKHR& surface; | ||||||
|     vk::CommandPool cmdpool; |     vk::CommandPool cmdpool; | ||||||
|     std::vector<Frame> frames; |     std::vector<Frame> frames; | ||||||
|     std::queue<Frame*> present_queue; |     std::queue<Frame*> present_queue; | ||||||
| @@ -77,7 +80,8 @@ private: | |||||||
|     std::jthread present_thread; |     std::jthread present_thread; | ||||||
|     bool blit_supported; |     bool blit_supported; | ||||||
|     bool use_present_thread; |     bool use_present_thread; | ||||||
|     std::size_t image_count; |     std::size_t image_count{}; | ||||||
|  |     void* last_render_surface{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Vulkan | } // namespace Vulkan | ||||||
|   | |||||||
| @@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap | |||||||
| Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, | ||||||
|                      u32 width_, u32 height_, bool srgb) |                      u32 width_, u32 height_, bool srgb) | ||||||
|     : surface{surface_}, device{device_}, scheduler{scheduler_} { |     : surface{surface_}, device{device_}, scheduler{scheduler_} { | ||||||
|     Create(width_, height_, srgb); |     Create(surface_, width_, height_, srgb); | ||||||
| } | } | ||||||
|  |  | ||||||
| Swapchain::~Swapchain() = default; | 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_outdated = false; | ||||||
|     is_suboptimal = false; |     is_suboptimal = false; | ||||||
|     width = width_; |     width = width_; | ||||||
|     height = height_; |     height = height_; | ||||||
|  |     surface = surface_; | ||||||
|  |  | ||||||
|     const auto physical_device = device.GetPhysical(); |     const auto physical_device = device.GetPhysical(); | ||||||
|     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; |     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ public: | |||||||
|     ~Swapchain(); |     ~Swapchain(); | ||||||
|  |  | ||||||
|     /// Creates (or recreates) the swapchain with a given size. |     /// 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. |     /// Acquires the next image in the swapchain, waits as needed. | ||||||
|     bool AcquireNextImage(); |     bool AcquireNextImage(); | ||||||
| @@ -118,7 +118,7 @@ private: | |||||||
|  |  | ||||||
|     bool NeedsPresentModeUpdate() const; |     bool NeedsPresentModeUpdate() const; | ||||||
|  |  | ||||||
|     const VkSurfaceKHR surface; |     VkSurfaceKHR surface; | ||||||
|     const Device& device; |     const Device& device; | ||||||
|     Scheduler& scheduler; |     Scheduler& scheduler; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user