Skip to content

Commit

Permalink
Vulkan: Fix possible mismatch between EFB framebuffer and render pass
Browse files Browse the repository at this point in the history
This could happen when changing MSAA settings or internal resolution at
runtime.
  • Loading branch information
stenzek committed Jan 11, 2018
1 parent 0525726 commit 4997fbc
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 29 deletions.
10 changes: 4 additions & 6 deletions Source/Core/VideoBackends/Vulkan/FramebufferManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/VideoBackends/Vulkan/FramebufferManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ class FramebufferManager : public FramebufferManagerBase
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.
Expand Down
29 changes: 9 additions & 20 deletions Source/Core/VideoBackends/Vulkan/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -735,32 +731,25 @@ 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.
// SSAA changed on/off, we have to recompile shaders.
// 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();
Expand Down Expand Up @@ -798,7 +787,7 @@ void Renderer::OnSwapChainResized()
m_backbuffer_height = m_swap_chain->GetHeight();
UpdateDrawRectangle();
if (CalculateTargetSize())
ResizeEFBTextures();
RecreateEFBFramebuffer();
}

void Renderer::BindEFBToStateTracker()
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/Vulkan/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Renderer : public ::Renderer

void OnSwapChainResized();
void BindEFBToStateTracker();
void ResizeEFBTextures();
void RecreateEFBFramebuffer();

void RecompileShaders();
bool CompileShaders();
Expand Down

0 comments on commit 4997fbc

Please sign in to comment.