summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/Renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/Renderer.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp116
1 files changed, 59 insertions, 57 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index 413f4bb750..7b65884075 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -500,6 +500,10 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->OnEndFrame();
+ // Handle host window resizes.
+ CheckForSurfaceChange();
+ CheckForSurfaceResize();
+
// There are a few variables which can alter the final window draw rectangle, and some of them
// are determined by guest state. Currently, the only way to catch these is to update every frame.
UpdateDrawRectangle();
@@ -543,9 +547,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
// Determine what (if anything) has changed in the config.
CheckForConfigChanges();
- // Handle host window resizes.
- CheckForSurfaceChange();
-
// Clean up stale textures.
TextureCache::GetInstance()->Cleanup(frameCount);
@@ -650,71 +651,83 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r
void Renderer::CheckForSurfaceChange()
{
- if (!m_surface_needs_change.IsSet())
+ if (!m_surface_changed.TestAndClear())
return;
- // Wait for the GPU to catch up since we're going to destroy the swap chain.
+ m_surface_handle = m_new_surface_handle;
+ m_new_surface_handle = nullptr;
+
+ // Submit the current draws up until rendering the XFB.
+ g_command_buffer_mgr->ExecuteCommandBuffer(false, false);
g_command_buffer_mgr->WaitForGPUIdle();
// Clear the present failed flag, since we don't want to resize after recreating.
g_command_buffer_mgr->CheckLastPresentFail();
- // Fast path, if the surface handle is the same, the window has just been resized.
- if (m_swap_chain && m_new_surface_handle == m_swap_chain->GetNativeHandle())
+ // Did we previously have a swap chain?
+ if (m_swap_chain)
{
- INFO_LOG(VIDEO, "Detected window resize.");
- m_swap_chain->RecreateSwapChain();
-
- // Notify the main thread we are done.
- m_surface_needs_change.Clear();
- m_new_surface_handle = nullptr;
- m_surface_changed.Set();
+ if (!m_surface_handle)
+ {
+ // If there is no surface now, destroy the swap chain.
+ m_swap_chain.reset();
+ }
+ else
+ {
+ // Recreate the surface. If this fails we're in trouble.
+ if (!m_swap_chain->RecreateSurface(m_surface_handle))
+ PanicAlert("Failed to recreate Vulkan surface. Cannot continue.");
+ }
}
else
{
- // Did we previously have a swap chain?
- if (m_swap_chain)
+ // Previously had no swap chain. So create one.
+ VkSurfaceKHR surface =
+ SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), m_surface_handle);
+ if (surface != VK_NULL_HANDLE)
{
- if (!m_new_surface_handle)
- {
- // If there is no surface now, destroy the swap chain.
- m_swap_chain.reset();
- }
- else
- {
- // Recreate the surface. If this fails we're in trouble.
- if (!m_swap_chain->RecreateSurface(m_new_surface_handle))
- PanicAlert("Failed to recreate Vulkan surface. Cannot continue.");
- }
+ m_swap_chain = SwapChain::Create(m_surface_handle, surface, g_ActiveConfig.IsVSync());
+ if (!m_swap_chain)
+ PanicAlert("Failed to create swap chain.");
}
else
{
- // Previously had no swap chain. So create one.
- VkSurfaceKHR surface = SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(),
- m_new_surface_handle);
- if (surface != VK_NULL_HANDLE)
- {
- m_swap_chain = SwapChain::Create(m_new_surface_handle, surface, g_ActiveConfig.IsVSync());
- if (!m_swap_chain)
- PanicAlert("Failed to create swap chain.");
- }
- else
- {
- PanicAlert("Failed to create surface.");
- }
+ PanicAlert("Failed to create surface.");
}
-
- // Notify calling thread.
- m_surface_needs_change.Clear();
- m_surface_handle = m_new_surface_handle;
- m_new_surface_handle = nullptr;
- m_surface_changed.Set();
}
// Handle case where the dimensions are now different.
OnSwapChainResized();
}
+void Renderer::CheckForSurfaceResize()
+{
+ if (!m_surface_resized.TestAndClear())
+ return;
+
+ m_backbuffer_width = m_new_backbuffer_width;
+ m_backbuffer_height = m_new_backbuffer_height;
+
+ // If we don't have a surface, how can we resize the swap chain?
+ // CheckForSurfaceChange should handle this case.
+ if (!m_swap_chain)
+ {
+ WARN_LOG(VIDEO, "Surface resize event received without active surface, ignoring");
+ return;
+ }
+
+ // Wait for the GPU to catch up since we're going to destroy the swap chain.
+ g_command_buffer_mgr->ExecuteCommandBuffer(false, false);
+ g_command_buffer_mgr->WaitForGPUIdle();
+
+ // Clear the present failed flag, since we don't want to resize after recreating.
+ g_command_buffer_mgr->CheckLastPresentFail();
+
+ // Resize the swap chain.
+ m_swap_chain->RecreateSwapChain();
+ OnSwapChainResized();
+}
+
void Renderer::CheckForConfigChanges()
{
// Save the video config so we can compare against to determine which settings have changed.
@@ -782,9 +795,6 @@ void Renderer::OnSwapChainResized()
{
m_backbuffer_width = m_swap_chain->GetWidth();
m_backbuffer_height = m_swap_chain->GetHeight();
- UpdateDrawRectangle();
- if (CalculateTargetSize())
- RecreateEFBFramebuffer();
}
void Renderer::BindEFBToStateTracker()
@@ -914,14 +924,6 @@ void Renderer::SetViewport(float x, float y, float width, float height, float ne
StateTracker::GetInstance()->SetViewport(viewport);
}
-void Renderer::ChangeSurface(void* new_surface_handle)
-{
- // Called by the main thread when the window is resized.
- m_new_surface_handle = new_surface_handle;
- m_surface_needs_change.Set();
- m_surface_changed.Set();
-}
-
void Renderer::RecompileShaders()
{
DestroyShaders();