FramebufferManager: Implement deferred EFB cache invalidation

This commit is contained in:
Stenzek 2019-03-02 17:05:38 +10:00
parent 6bc4bfd26a
commit a218a794cb
11 changed files with 42 additions and 14 deletions

View File

@ -136,6 +136,8 @@ const ConfigInfo<int> GFX_STEREO_DEPTH_PERCENTAGE{
// Graphics.Hacks // Graphics.Hacks
const ConfigInfo<bool> GFX_HACK_EFB_ACCESS_ENABLE{{System::GFX, "Hacks", "EFBAccessEnable"}, true}; const ConfigInfo<bool> GFX_HACK_EFB_ACCESS_ENABLE{{System::GFX, "Hacks", "EFBAccessEnable"}, true};
const ConfigInfo<bool> GFX_HACK_EFB_DEFER_INVALIDATION{
{System::GFX, "Hacks", "EFBAccessDeferInvalidation"}, false};
const ConfigInfo<int> GFX_HACK_EFB_ACCESS_TILE_SIZE{{System::GFX, "Hacks", "EFBAccessTileSize"}, const ConfigInfo<int> GFX_HACK_EFB_ACCESS_TILE_SIZE{{System::GFX, "Hacks", "EFBAccessTileSize"},
64}; 64};
const ConfigInfo<bool> GFX_HACK_BBOX_ENABLE{{System::GFX, "Hacks", "BBoxEnable"}, false}; const ConfigInfo<bool> GFX_HACK_BBOX_ENABLE{{System::GFX, "Hacks", "BBoxEnable"}, false};

View File

@ -101,6 +101,7 @@ extern const ConfigInfo<int> GFX_STEREO_DEPTH_PERCENTAGE;
// Graphics.Hacks // Graphics.Hacks
extern const ConfigInfo<bool> GFX_HACK_EFB_ACCESS_ENABLE; extern const ConfigInfo<bool> GFX_HACK_EFB_ACCESS_ENABLE;
extern const ConfigInfo<bool> GFX_HACK_EFB_DEFER_INVALIDATION;
extern const ConfigInfo<int> GFX_HACK_EFB_ACCESS_TILE_SIZE; extern const ConfigInfo<int> GFX_HACK_EFB_ACCESS_TILE_SIZE;
extern const ConfigInfo<bool> GFX_HACK_BBOX_ENABLE; extern const ConfigInfo<bool> GFX_HACK_BBOX_ENABLE;
extern const ConfigInfo<bool> GFX_HACK_FORCE_PROGRESSIVE; extern const ConfigInfo<bool> GFX_HACK_FORCE_PROGRESSIVE;

View File

@ -113,6 +113,7 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
// Graphics.Hacks // Graphics.Hacks
Config::GFX_HACK_EFB_ACCESS_ENABLE.location, 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_EFB_ACCESS_TILE_SIZE.location,
Config::GFX_HACK_BBOX_ENABLE.location, Config::GFX_HACK_BBOX_ENABLE.location,
Config::GFX_HACK_FORCE_PROGRESSIVE.location, Config::GFX_HACK_FORCE_PROGRESSIVE.location,

View File

@ -939,7 +939,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
u32 color, u32 z) u32 color, u32 z)
{ {
g_framebuffer_manager->FlushEFBPokes(); g_framebuffer_manager->FlushEFBPokes();
g_framebuffer_manager->InvalidatePeekCache(); g_framebuffer_manager->FlagPeekCacheAsOutOfDate();
u32 clear_mask = 0; u32 clear_mask = 0;
if (colorEnable || alphaEnable) if (colorEnable || alphaEnable)

View File

@ -186,7 +186,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
bool z_enable, u32 color, u32 z) bool z_enable, u32 color, u32 z)
{ {
g_framebuffer_manager->FlushEFBPokes(); g_framebuffer_manager->FlushEFBPokes();
g_framebuffer_manager->InvalidatePeekCache(); g_framebuffer_manager->FlagPeekCacheAsOutOfDate();
// Native -> EFB coordinates // Native -> EFB coordinates
TargetRectangle target_rc = Renderer::ConvertEFBRectangle(rc); TargetRectangle target_rc = Renderer::ConvertEFBRectangle(rc);

View File

@ -22,6 +22,7 @@
#include "VideoCommon/BPMemory.h" #include "VideoCommon/BPMemory.h"
#include "VideoCommon/BoundingBox.h" #include "VideoCommon/BoundingBox.h"
#include "VideoCommon/Fifo.h" #include "VideoCommon/Fifo.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/PerfQueryBase.h" #include "VideoCommon/PerfQueryBase.h"
#include "VideoCommon/PixelEngine.h" #include "VideoCommon/PixelEngine.h"
@ -178,6 +179,7 @@ static void BPWritten(const BPCmd& bp)
{ {
case 0x02: case 0x02:
g_texture_cache->FlushEFBCopies(); g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread()) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetFinish(); // may generate interrupt PixelEngine::SetFinish(); // may generate interrupt
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF));
@ -190,12 +192,14 @@ static void BPWritten(const BPCmd& bp)
return; return;
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
g_texture_cache->FlushEFBCopies(); g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread()) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false); PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false);
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF));
return; return;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
g_texture_cache->FlushEFBCopies(); g_texture_cache->FlushEFBCopies();
g_framebuffer_manager->InvalidatePeekCache(false);
if (!Fifo::UseDeterministicGPUThread()) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true); PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true);
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF));

View File

@ -80,7 +80,7 @@ bool FramebufferManager::Initialize()
void FramebufferManager::RecreateEFBFramebuffer() void FramebufferManager::RecreateEFBFramebuffer()
{ {
FlushEFBPokes(); FlushEFBPokes();
InvalidatePeekCache(); InvalidatePeekCache(true);
DestroyReadbackFramebuffer(); DestroyReadbackFramebuffer();
DestroyEFBFramebuffer(); 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_color_texture, m_efb_convert_color_texture);
std::swap(m_efb_framebuffer, m_efb_convert_framebuffer); std::swap(m_efb_framebuffer, m_efb_convert_framebuffer);
g_renderer->EndUtilityDrawing(); g_renderer->EndUtilityDrawing();
InvalidatePeekCache(); InvalidatePeekCache(true);
return true; return true;
} }
@ -396,27 +396,40 @@ void FramebufferManager::SetEFBCacheTileSize(u32 size)
if (m_efb_cache_tile_size == size) if (m_efb_cache_tile_size == size)
return; return;
InvalidatePeekCache(); InvalidatePeekCache(true);
m_efb_cache_tile_size = size; m_efb_cache_tile_size = size;
DestroyReadbackFramebuffer(); DestroyReadbackFramebuffer();
if (!CreateReadbackFramebuffer()) if (!CreateReadbackFramebuffer())
PanicAlert("Failed to create EFB readback framebuffers"); 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.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); 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.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); 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() bool FramebufferManager::CompileReadbackPipelines()
{ {
AbstractPipelineConfig config = {}; AbstractPipelineConfig config = {};
@ -580,6 +593,7 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index)
// Wait until the copy is complete. // Wait until the copy is complete.
data.readback_texture->Flush(); data.readback_texture->Flush();
data.valid = true; data.valid = true;
data.out_of_date = false;
if (IsUsingTiledEFBCache()) if (IsUsingTiledEFBCache())
data.tiles[tile_index] = true; data.tiles[tile_index] = true;
} }
@ -588,7 +602,7 @@ void FramebufferManager::ClearEFB(const MathUtil::Rectangle<int>& rc, bool clear
bool clear_alpha, bool clear_z, u32 color, u32 z) bool clear_alpha, bool clear_z, u32 color, u32 z)
{ {
FlushEFBPokes(); FlushEFBPokes();
InvalidatePeekCache(); FlagPeekCacheAsOutOfDate();
g_renderer->BeginUtilityDrawing(); g_renderer->BeginUtilityDrawing();
// Set up uniforms. // Set up uniforms.

View File

@ -9,10 +9,10 @@
#include <optional> #include <optional>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/AbstractFramebuffer.h" #include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/RenderState.h" #include "VideoCommon/RenderState.h"
#include "VideoCommon/TextureConfig.h" #include "VideoCommon/TextureConfig.h"
@ -87,7 +87,8 @@ public:
u32 PeekEFBColor(u32 x, u32 y); u32 PeekEFBColor(u32 x, u32 y);
float PeekEFBDepth(u32 x, u32 y); float PeekEFBDepth(u32 x, u32 y);
void SetEFBCacheTileSize(u32 size); 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. // Writes a value to the framebuffer. This will never block, and writes will be batched.
void PokeEFBColor(u32 x, u32 y, u32 color); void PokeEFBColor(u32 x, u32 y, u32 color);
@ -111,6 +112,7 @@ protected:
std::unique_ptr<AbstractStagingTexture> readback_texture; std::unique_ptr<AbstractStagingTexture> readback_texture;
std::unique_ptr<AbstractPipeline> copy_pipeline; std::unique_ptr<AbstractPipeline> copy_pipeline;
std::vector<bool> tiles; std::vector<bool> tiles;
bool out_of_date;
bool valid; bool valid;
}; };

View File

@ -99,8 +99,7 @@ u32 VertexManagerBase::GetRemainingSize() const
DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride, DataReader VertexManagerBase::PrepareForAdditionalData(int primitive, u32 count, u32 stride,
bool cullall) bool cullall)
{ {
// Flush all EFB pokes and invalidate the peek cache. // Flush all EFB pokes. Since the buffer is shared, we can't draw pokes+primitives concurrently.
g_framebuffer_manager->InvalidatePeekCache();
g_framebuffer_manager->FlushEFBPokes(); g_framebuffer_manager->FlushEFBPokes();
// The SSE vertex loader can write up to 4 bytes past the end // 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); g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
OnDraw(); OnDraw();
// The EFB cache is now potentially stale.
g_framebuffer_manager->FlagPeekCacheAsOutOfDate();
} }
} }

View File

@ -144,6 +144,7 @@ void VideoConfig::Refresh()
iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE); iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE);
bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE); 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); bBBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE); bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM); bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);

View File

@ -112,6 +112,7 @@ struct VideoConfig final
// Hacks // Hacks
bool bEFBAccessEnable; bool bEFBAccessEnable;
bool bEFBAccessDeferInvalidation;
bool bPerfQueriesEnable; bool bPerfQueriesEnable;
bool bBBoxEnable; bool bBBoxEnable;
bool bForceProgressive; bool bForceProgressive;