Vulkan: Submit fewer command buffers in deferred EFB copies mode

This commit is contained in:
Stenzek 2018-11-05 23:09:34 +10:00
parent 8e2c063d62
commit 66b6e72c5e
4 changed files with 29 additions and 6 deletions

View File

@ -611,7 +611,7 @@ bool FramebufferManager::PopulateColorReadbackTexture()
{ {
// Can't be in our normal render pass. // Can't be in our normal render pass.
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->OnReadback(); StateTracker::GetInstance()->OnCPUEFBAccess();
// Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on. // Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on.
VkRect2D src_region = {{0, 0}, {GetEFBWidth(), GetEFBHeight()}}; VkRect2D src_region = {{0, 0}, {GetEFBWidth(), GetEFBHeight()}};
@ -684,7 +684,7 @@ bool FramebufferManager::PopulateDepthReadbackTexture()
{ {
// Can't be in our normal render pass. // Can't be in our normal render pass.
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->OnReadback(); StateTracker::GetInstance()->OnCPUEFBAccess();
// Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on. // Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on.
VkRect2D src_region = {{0, 0}, {GetEFBWidth(), GetEFBHeight()}}; VkRect2D src_region = {{0, 0}, {GetEFBWidth(), GetEFBHeight()}};

View File

@ -513,7 +513,7 @@ void StateTracker::OnDraw()
} }
} }
void StateTracker::OnReadback() void StateTracker::OnCPUEFBAccess()
{ {
// Check this isn't another access without any draws inbetween. // Check this isn't another access without any draws inbetween.
if (!m_cpu_accesses_this_frame.empty() && m_cpu_accesses_this_frame.back() == m_draw_counter) if (!m_cpu_accesses_this_frame.empty() && m_cpu_accesses_this_frame.back() == m_draw_counter)
@ -523,9 +523,28 @@ void StateTracker::OnReadback()
m_cpu_accesses_this_frame.emplace_back(m_draw_counter); m_cpu_accesses_this_frame.emplace_back(m_draw_counter);
} }
void StateTracker::OnEFBCopyToRAM()
{
// If we're not deferring, try to preempt it next frame.
if (!g_ActiveConfig.bDeferEFBCopies)
{
OnCPUEFBAccess();
return;
}
// Otherwise, only execute if we have at least 10 objects between us and the last copy.
const u32 diff = m_draw_counter - m_last_efb_copy_draw_counter;
m_last_efb_copy_draw_counter = m_draw_counter;
if (diff < MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK)
return;
Util::ExecuteCurrentCommandsAndRestoreState(true);
}
void StateTracker::OnEndFrame() void StateTracker::OnEndFrame()
{ {
m_draw_counter = 0; m_draw_counter = 0;
m_last_efb_copy_draw_counter = 0;
m_scheduled_command_buffer_kicks.clear(); m_scheduled_command_buffer_kicks.clear();
// If we have no CPU access at all, leave everything in the one command buffer for maximum // If we have no CPU access at all, leave everything in the one command buffer for maximum

View File

@ -86,8 +86,10 @@ public:
void OnDraw(); void OnDraw();
// Call after CPU access is requested. // Call after CPU access is requested.
// This can be via EFBCache or EFB2RAM. void OnCPUEFBAccess();
void OnReadback();
// Call after an EFB copy to RAM. If true, the current command buffer should be executed.
void OnEFBCopyToRAM();
// Call at the end of a frame. // Call at the end of a frame.
void OnEndFrame(); void OnEndFrame();
@ -182,6 +184,7 @@ private:
// CPU access tracking // CPU access tracking
u32 m_draw_counter = 0; u32 m_draw_counter = 0;
u32 m_last_efb_copy_draw_counter = 0;
std::vector<u32> m_cpu_accesses_this_frame; std::vector<u32> m_cpu_accesses_this_frame;
std::vector<u32> m_scheduled_command_buffer_kicks; std::vector<u32> m_scheduled_command_buffer_kicks;
bool m_allow_background_execution = true; bool m_allow_background_execution = true;

View File

@ -126,7 +126,6 @@ void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& par
// The barrier has to happen after the render pass, not inside it, as we are going to be // The barrier has to happen after the render pass, not inside it, as we are going to be
// reading from the texture immediately afterwards. // reading from the texture immediately afterwards.
StateTracker::GetInstance()->EndRenderPass(); StateTracker::GetInstance()->EndRenderPass();
StateTracker::GetInstance()->OnReadback();
// Transition to shader resource before reading. // Transition to shader resource before reading.
VkImageLayout original_layout = src_texture->GetLayout(); VkImageLayout original_layout = src_texture->GetLayout();
@ -139,6 +138,8 @@ void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& par
// Transition back to original state // Transition back to original state
src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout); src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout);
StateTracker::GetInstance()->OnEFBCopyToRAM();
} }
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format) bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format)