From 4997fbce44f9d092c503ce34f92faafb1af1dd44 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 11 Jan 2018 16:02:31 +1000 Subject: [PATCH] Vulkan: Fix possible mismatch between EFB framebuffer and render pass This could happen when changing MSAA settings or internal resolution at runtime. --- .../Vulkan/FramebufferManager.cpp | 10 +++---- .../VideoBackends/Vulkan/FramebufferManager.h | 3 +- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 29 ++++++------------- Source/Core/VideoBackends/Vulkan/Renderer.h | 2 +- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp index bf13701600..9c2c712837 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp @@ -318,17 +318,15 @@ void FramebufferManager::DestroyEFBFramebuffer() m_efb_resolve_depth_texture.reset(); } -void FramebufferManager::ResizeEFBTextures() +void FramebufferManager::RecreateEFBFramebuffer() { DestroyEFBFramebuffer(); - if (!CreateEFBFramebuffer()) - PanicAlert("Failed to create EFB textures"); -} -void FramebufferManager::RecreateRenderPass() -{ if (!CreateEFBRenderPasses()) PanicAlert("Failed to create EFB render pass"); + + if (!CreateEFBFramebuffer()) + PanicAlert("Failed to create EFB textures"); } void FramebufferManager::RecompileShaders() diff --git a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h index 0a731881db..f037564e1c 100644 --- a/Source/Core/VideoBackends/Vulkan/FramebufferManager.h +++ b/Source/Core/VideoBackends/Vulkan/FramebufferManager.h @@ -45,10 +45,9 @@ public: VkSampleCountFlagBits GetEFBSamples() const; MultisamplingState GetEFBMultisamplingState() const; - void ResizeEFBTextures(); + void RecreateEFBFramebuffer(); // Recompile shaders, use when MSAA mode changes. - void RecreateRenderPass(); void RecompileShaders(); // Reinterpret pixel format of EFB color texture. diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 742a525b98..a146351007 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -545,9 +545,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region // Handle host window resizes. CheckForSurfaceChange(); - if (CalculateTargetSize()) - ResizeEFBTextures(); - // Update the window size based on the frame that was just rendered. // Due to depending on guest state, we need to call this every frame. SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height); @@ -724,9 +721,8 @@ void Renderer::CheckForSurfaceChange() void Renderer::CheckForConfigChanges() { // Save the video config so we can compare against to determine which settings have changed. + const u32 old_multisamples = g_ActiveConfig.iMultisamples; const int old_anisotropy = g_ActiveConfig.iMaxAnisotropy; - const AspectMode old_aspect_mode = g_ActiveConfig.aspect_mode; - const int old_efb_scale = g_ActiveConfig.iEFBScale; const bool old_force_filtering = g_ActiveConfig.bForceFiltering; // Copy g_Config to g_ActiveConfig. @@ -735,21 +731,17 @@ void Renderer::CheckForConfigChanges() UpdateActiveConfig(); // Determine which (if any) settings have changed. + const bool multisamples_changed = old_multisamples != g_ActiveConfig.iMultisamples; const bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy; const bool force_texture_filtering_changed = old_force_filtering != g_ActiveConfig.bForceFiltering; - const bool efb_scale_changed = old_efb_scale != g_ActiveConfig.iEFBScale; - const bool aspect_changed = old_aspect_mode != g_ActiveConfig.aspect_mode; // Update texture cache settings with any changed options. TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig); - // Handle settings that can cause the target rectangle to change. - if (efb_scale_changed || aspect_changed) - { - if (CalculateTargetSize()) - ResizeEFBTextures(); - } + // Handle settings that can cause the EFB framebuffer to change. + if (CalculateTargetSize() || multisamples_changed) + RecreateEFBFramebuffer(); // MSAA samples changed, we need to recreate the EFB render pass. // If the stereoscopy mode changed, we need to recreate the buffers as well. @@ -757,10 +749,7 @@ void Renderer::CheckForConfigChanges() // Changing stereoscopy from off<->on also requires shaders to be recompiled. if (CheckForHostConfigChanges()) { - g_command_buffer_mgr->WaitForGPUIdle(); - FramebufferManager::GetInstance()->RecreateRenderPass(); - FramebufferManager::GetInstance()->ResizeEFBTextures(); - BindEFBToStateTracker(); + RecreateEFBFramebuffer(); RecompileShaders(); FramebufferManager::GetInstance()->RecompileShaders(); g_shader_cache->ReloadShaderAndPipelineCaches(); @@ -798,7 +787,7 @@ void Renderer::OnSwapChainResized() m_backbuffer_height = m_swap_chain->GetHeight(); UpdateDrawRectangle(); if (CalculateTargetSize()) - ResizeEFBTextures(); + RecreateEFBFramebuffer(); } void Renderer::BindEFBToStateTracker() @@ -816,11 +805,11 @@ void Renderer::BindEFBToStateTracker() FramebufferManager::GetInstance()->GetEFBMultisamplingState()); } -void Renderer::ResizeEFBTextures() +void Renderer::RecreateEFBFramebuffer() { // Ensure the GPU is finished with the current EFB textures. g_command_buffer_mgr->WaitForGPUIdle(); - FramebufferManager::GetInstance()->ResizeEFBTextures(); + FramebufferManager::GetInstance()->RecreateEFBFramebuffer(); BindEFBToStateTracker(); // Viewport and scissor rect have to be reset since they will be scaled differently. diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index b3f8168347..5a994bf597 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -82,7 +82,7 @@ private: void OnSwapChainResized(); void BindEFBToStateTracker(); - void ResizeEFBTextures(); + void RecreateEFBFramebuffer(); void RecompileShaders(); bool CompileShaders();