diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index cd6a75c34e..3913176f2b 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -136,6 +136,8 @@ const ConfigInfo GFX_STEREO_DEPTH_PERCENTAGE{ // Graphics.Hacks const ConfigInfo GFX_HACK_EFB_ACCESS_ENABLE{{System::GFX, "Hacks", "EFBAccessEnable"}, true}; +const ConfigInfo GFX_HACK_EFB_DEFER_INVALIDATION{ + {System::GFX, "Hacks", "EFBAccessDeferInvalidation"}, false}; const ConfigInfo GFX_HACK_EFB_ACCESS_TILE_SIZE{{System::GFX, "Hacks", "EFBAccessTileSize"}, 64}; const ConfigInfo GFX_HACK_BBOX_ENABLE{{System::GFX, "Hacks", "BBoxEnable"}, false}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index bcc251c3ce..1946e704fc 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -101,6 +101,7 @@ extern const ConfigInfo GFX_STEREO_DEPTH_PERCENTAGE; // Graphics.Hacks extern const ConfigInfo GFX_HACK_EFB_ACCESS_ENABLE; +extern const ConfigInfo GFX_HACK_EFB_DEFER_INVALIDATION; extern const ConfigInfo GFX_HACK_EFB_ACCESS_TILE_SIZE; extern const ConfigInfo GFX_HACK_BBOX_ENABLE; extern const ConfigInfo GFX_HACK_FORCE_PROGRESSIVE; diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index aa0735ec62..5180169353 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -113,6 +113,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) // Graphics.Hacks Config::GFX_HACK_EFB_ACCESS_ENABLE.location, + Config::GFX_HACK_EFB_DEFER_INVALIDATION.location, Config::GFX_HACK_EFB_ACCESS_TILE_SIZE.location, Config::GFX_HACK_BBOX_ENABLE.location, Config::GFX_HACK_FORCE_PROGRESSIVE.location, diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index baeb9f877c..d0f3e74c5a 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -939,7 +939,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE u32 color, u32 z) { g_framebuffer_manager->FlushEFBPokes(); - g_framebuffer_manager->InvalidatePeekCache(); + g_framebuffer_manager->FlagPeekCacheAsOutOfDate(); u32 clear_mask = 0; if (colorEnable || alphaEnable) diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 0254f128a8..ae3c7c5807 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -186,7 +186,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha bool z_enable, u32 color, u32 z) { g_framebuffer_manager->FlushEFBPokes(); - g_framebuffer_manager->InvalidatePeekCache(); + g_framebuffer_manager->FlagPeekCacheAsOutOfDate(); // Native -> EFB coordinates TargetRectangle target_rc = Renderer::ConvertEFBRectangle(rc); diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 7712421f57..b234cec785 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -22,6 +22,7 @@ #include "VideoCommon/BPMemory.h" #include "VideoCommon/BoundingBox.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/FramebufferManager.h" #include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/PerfQueryBase.h" #include "VideoCommon/PixelEngine.h" @@ -178,6 +179,7 @@ static void BPWritten(const BPCmd& bp) { case 0x02: g_texture_cache->FlushEFBCopies(); + g_framebuffer_manager->InvalidatePeekCache(false); if (!Fifo::UseDeterministicGPUThread()) PixelEngine::SetFinish(); // may generate interrupt DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF)); @@ -190,12 +192,14 @@ static void BPWritten(const BPCmd& bp) return; case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID g_texture_cache->FlushEFBCopies(); + g_framebuffer_manager->InvalidatePeekCache(false); if (!Fifo::UseDeterministicGPUThread()) PixelEngine::SetToken(static_cast(bp.newvalue & 0xFFFF), false); DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF)); return; case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID g_texture_cache->FlushEFBCopies(); + g_framebuffer_manager->InvalidatePeekCache(false); if (!Fifo::UseDeterministicGPUThread()) PixelEngine::SetToken(static_cast(bp.newvalue & 0xFFFF), true); DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF)); diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp index ec055a7278..489ce62292 100644 --- a/Source/Core/VideoCommon/FramebufferManager.cpp +++ b/Source/Core/VideoCommon/FramebufferManager.cpp @@ -80,7 +80,7 @@ bool FramebufferManager::Initialize() void FramebufferManager::RecreateEFBFramebuffer() { FlushEFBPokes(); - InvalidatePeekCache(); + InvalidatePeekCache(true); DestroyReadbackFramebuffer(); DestroyEFBFramebuffer(); @@ -289,7 +289,7 @@ bool FramebufferManager::ReinterpretPixelData(EFBReinterpretType convtype) std::swap(m_efb_color_texture, m_efb_convert_color_texture); std::swap(m_efb_framebuffer, m_efb_convert_framebuffer); g_renderer->EndUtilityDrawing(); - InvalidatePeekCache(); + InvalidatePeekCache(true); return true; } @@ -396,27 +396,40 @@ void FramebufferManager::SetEFBCacheTileSize(u32 size) if (m_efb_cache_tile_size == size) return; - InvalidatePeekCache(); + InvalidatePeekCache(true); m_efb_cache_tile_size = size; DestroyReadbackFramebuffer(); if (!CreateReadbackFramebuffer()) PanicAlert("Failed to create EFB readback framebuffers"); } -void FramebufferManager::InvalidatePeekCache() +void FramebufferManager::InvalidatePeekCache(bool forced) { - if (m_efb_color_cache.valid) + if (forced || m_efb_color_cache.out_of_date) { m_efb_color_cache.valid = false; + m_efb_color_cache.out_of_date = false; std::fill(m_efb_color_cache.tiles.begin(), m_efb_color_cache.tiles.end(), false); } - if (m_efb_depth_cache.valid) + if (forced || m_efb_depth_cache.out_of_date) { m_efb_depth_cache.valid = false; + m_efb_depth_cache.out_of_date = false; std::fill(m_efb_depth_cache.tiles.begin(), m_efb_depth_cache.tiles.end(), false); } } +void FramebufferManager::FlagPeekCacheAsOutOfDate() +{ + if (m_efb_color_cache.valid) + m_efb_color_cache.out_of_date = true; + if (m_efb_depth_cache.valid) + m_efb_depth_cache.out_of_date = true; + + if (!g_ActiveConfig.bEFBAccessDeferInvalidation) + InvalidatePeekCache(); +} + bool FramebufferManager::CompileReadbackPipelines() { AbstractPipelineConfig config = {}; @@ -580,6 +593,7 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index) // Wait until the copy is complete. data.readback_texture->Flush(); data.valid = true; + data.out_of_date = false; if (IsUsingTiledEFBCache()) data.tiles[tile_index] = true; } @@ -588,7 +602,7 @@ void FramebufferManager::ClearEFB(const MathUtil::Rectangle& rc, bool clear bool clear_alpha, bool clear_z, u32 color, u32 z) { FlushEFBPokes(); - InvalidatePeekCache(); + FlagPeekCacheAsOutOfDate(); g_renderer->BeginUtilityDrawing(); // Set up uniforms. diff --git a/Source/Core/VideoCommon/FramebufferManager.h b/Source/Core/VideoCommon/FramebufferManager.h index b6fb53f949..b97d45b31e 100644 --- a/Source/Core/VideoCommon/FramebufferManager.h +++ b/Source/Core/VideoCommon/FramebufferManager.h @@ -9,10 +9,10 @@ #include #include "Common/CommonTypes.h" -#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/AbstractFramebuffer.h" -#include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/AbstractPipeline.h" +#include "VideoCommon/AbstractStagingTexture.h" +#include "VideoCommon/AbstractTexture.h" #include "VideoCommon/RenderState.h" #include "VideoCommon/TextureConfig.h" @@ -87,7 +87,8 @@ public: u32 PeekEFBColor(u32 x, u32 y); float PeekEFBDepth(u32 x, u32 y); void SetEFBCacheTileSize(u32 size); - void InvalidatePeekCache(); + void InvalidatePeekCache(bool forced = true); + void FlagPeekCacheAsOutOfDate(); // Writes a value to the framebuffer. This will never block, and writes will be batched. void PokeEFBColor(u32 x, u32 y, u32 color); @@ -111,6 +112,7 @@ protected: std::unique_ptr readback_texture; std::unique_ptr copy_pipeline; std::vector tiles; + bool out_of_date; bool valid; }; diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index bbc355a98c..06168c6cec 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -99,8 +99,7 @@ u32 VertexManagerBase::GetRemainingSize() const DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall) { - // Flush all EFB pokes and invalidate the peek cache. - g_framebuffer_manager->InvalidatePeekCache(); + // Flush all EFB pokes. Since the buffer is shared, we can't draw pokes+primitives concurrently. g_framebuffer_manager->FlushEFBPokes(); // The SSE vertex loader can write up to 4 bytes past the end @@ -449,6 +448,9 @@ void VertexManagerBase::Flush() g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); OnDraw(); + + // The EFB cache is now potentially stale. + g_framebuffer_manager->FlagPeekCacheAsOutOfDate(); } } diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 2385d427a2..bfd4a6b99b 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -144,6 +144,7 @@ void VideoConfig::Refresh() iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE); bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE); + bEFBAccessDeferInvalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION); bBBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE); bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE); bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index c6d00162ce..5be2a06639 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -112,6 +112,7 @@ struct VideoConfig final // Hacks bool bEFBAccessEnable; + bool bEFBAccessDeferInvalidation; bool bPerfQueriesEnable; bool bBBoxEnable; bool bForceProgressive;