Vulkan: Fix possible mismatch between EFB framebuffer and render pass
This could happen when changing MSAA settings or internal resolution at runtime.
This commit is contained in:
parent
0525726338
commit
4997fbce44
|
@ -318,17 +318,15 @@ void FramebufferManager::DestroyEFBFramebuffer()
|
||||||
m_efb_resolve_depth_texture.reset();
|
m_efb_resolve_depth_texture.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::ResizeEFBTextures()
|
void FramebufferManager::RecreateEFBFramebuffer()
|
||||||
{
|
{
|
||||||
DestroyEFBFramebuffer();
|
DestroyEFBFramebuffer();
|
||||||
if (!CreateEFBFramebuffer())
|
|
||||||
PanicAlert("Failed to create EFB textures");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramebufferManager::RecreateRenderPass()
|
|
||||||
{
|
|
||||||
if (!CreateEFBRenderPasses())
|
if (!CreateEFBRenderPasses())
|
||||||
PanicAlert("Failed to create EFB render pass");
|
PanicAlert("Failed to create EFB render pass");
|
||||||
|
|
||||||
|
if (!CreateEFBFramebuffer())
|
||||||
|
PanicAlert("Failed to create EFB textures");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::RecompileShaders()
|
void FramebufferManager::RecompileShaders()
|
||||||
|
|
|
@ -45,10 +45,9 @@ public:
|
||||||
VkSampleCountFlagBits GetEFBSamples() const;
|
VkSampleCountFlagBits GetEFBSamples() const;
|
||||||
MultisamplingState GetEFBMultisamplingState() const;
|
MultisamplingState GetEFBMultisamplingState() const;
|
||||||
|
|
||||||
void ResizeEFBTextures();
|
void RecreateEFBFramebuffer();
|
||||||
|
|
||||||
// Recompile shaders, use when MSAA mode changes.
|
// Recompile shaders, use when MSAA mode changes.
|
||||||
void RecreateRenderPass();
|
|
||||||
void RecompileShaders();
|
void RecompileShaders();
|
||||||
|
|
||||||
// Reinterpret pixel format of EFB color texture.
|
// Reinterpret pixel format of EFB color texture.
|
||||||
|
|
|
@ -545,9 +545,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
|
||||||
// Handle host window resizes.
|
// Handle host window resizes.
|
||||||
CheckForSurfaceChange();
|
CheckForSurfaceChange();
|
||||||
|
|
||||||
if (CalculateTargetSize())
|
|
||||||
ResizeEFBTextures();
|
|
||||||
|
|
||||||
// Update the window size based on the frame that was just rendered.
|
// 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.
|
// Due to depending on guest state, we need to call this every frame.
|
||||||
SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);
|
SetWindowSize(xfb_texture->GetConfig().width, xfb_texture->GetConfig().height);
|
||||||
|
@ -724,9 +721,8 @@ void Renderer::CheckForSurfaceChange()
|
||||||
void Renderer::CheckForConfigChanges()
|
void Renderer::CheckForConfigChanges()
|
||||||
{
|
{
|
||||||
// Save the video config so we can compare against to determine which settings have changed.
|
// 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 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;
|
const bool old_force_filtering = g_ActiveConfig.bForceFiltering;
|
||||||
|
|
||||||
// Copy g_Config to g_ActiveConfig.
|
// Copy g_Config to g_ActiveConfig.
|
||||||
|
@ -735,21 +731,17 @@ void Renderer::CheckForConfigChanges()
|
||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
|
|
||||||
// Determine which (if any) settings have changed.
|
// 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 anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
|
||||||
const bool force_texture_filtering_changed =
|
const bool force_texture_filtering_changed =
|
||||||
old_force_filtering != g_ActiveConfig.bForceFiltering;
|
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.
|
// Update texture cache settings with any changed options.
|
||||||
TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig);
|
TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig);
|
||||||
|
|
||||||
// Handle settings that can cause the target rectangle to change.
|
// Handle settings that can cause the EFB framebuffer to change.
|
||||||
if (efb_scale_changed || aspect_changed)
|
if (CalculateTargetSize() || multisamples_changed)
|
||||||
{
|
RecreateEFBFramebuffer();
|
||||||
if (CalculateTargetSize())
|
|
||||||
ResizeEFBTextures();
|
|
||||||
}
|
|
||||||
|
|
||||||
// MSAA samples changed, we need to recreate the EFB render pass.
|
// MSAA samples changed, we need to recreate the EFB render pass.
|
||||||
// If the stereoscopy mode changed, we need to recreate the buffers as well.
|
// 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.
|
// Changing stereoscopy from off<->on also requires shaders to be recompiled.
|
||||||
if (CheckForHostConfigChanges())
|
if (CheckForHostConfigChanges())
|
||||||
{
|
{
|
||||||
g_command_buffer_mgr->WaitForGPUIdle();
|
RecreateEFBFramebuffer();
|
||||||
FramebufferManager::GetInstance()->RecreateRenderPass();
|
|
||||||
FramebufferManager::GetInstance()->ResizeEFBTextures();
|
|
||||||
BindEFBToStateTracker();
|
|
||||||
RecompileShaders();
|
RecompileShaders();
|
||||||
FramebufferManager::GetInstance()->RecompileShaders();
|
FramebufferManager::GetInstance()->RecompileShaders();
|
||||||
g_shader_cache->ReloadShaderAndPipelineCaches();
|
g_shader_cache->ReloadShaderAndPipelineCaches();
|
||||||
|
@ -798,7 +787,7 @@ void Renderer::OnSwapChainResized()
|
||||||
m_backbuffer_height = m_swap_chain->GetHeight();
|
m_backbuffer_height = m_swap_chain->GetHeight();
|
||||||
UpdateDrawRectangle();
|
UpdateDrawRectangle();
|
||||||
if (CalculateTargetSize())
|
if (CalculateTargetSize())
|
||||||
ResizeEFBTextures();
|
RecreateEFBFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::BindEFBToStateTracker()
|
void Renderer::BindEFBToStateTracker()
|
||||||
|
@ -816,11 +805,11 @@ void Renderer::BindEFBToStateTracker()
|
||||||
FramebufferManager::GetInstance()->GetEFBMultisamplingState());
|
FramebufferManager::GetInstance()->GetEFBMultisamplingState());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::ResizeEFBTextures()
|
void Renderer::RecreateEFBFramebuffer()
|
||||||
{
|
{
|
||||||
// Ensure the GPU is finished with the current EFB textures.
|
// Ensure the GPU is finished with the current EFB textures.
|
||||||
g_command_buffer_mgr->WaitForGPUIdle();
|
g_command_buffer_mgr->WaitForGPUIdle();
|
||||||
FramebufferManager::GetInstance()->ResizeEFBTextures();
|
FramebufferManager::GetInstance()->RecreateEFBFramebuffer();
|
||||||
BindEFBToStateTracker();
|
BindEFBToStateTracker();
|
||||||
|
|
||||||
// Viewport and scissor rect have to be reset since they will be scaled differently.
|
// Viewport and scissor rect have to be reset since they will be scaled differently.
|
||||||
|
|
|
@ -82,7 +82,7 @@ private:
|
||||||
|
|
||||||
void OnSwapChainResized();
|
void OnSwapChainResized();
|
||||||
void BindEFBToStateTracker();
|
void BindEFBToStateTracker();
|
||||||
void ResizeEFBTextures();
|
void RecreateEFBFramebuffer();
|
||||||
|
|
||||||
void RecompileShaders();
|
void RecompileShaders();
|
||||||
bool CompileShaders();
|
bool CompileShaders();
|
||||||
|
|
Loading…
Reference in New Issue