Skip to content
Permalink
Browse files

FramebufferManager: Implement deferred EFB cache invalidation

  • Loading branch information...
stenzek committed Mar 2, 2019
1 parent 6bc4bfd commit a218a794cb365690fe33099be14fbf3b08de5d33
@@ -136,6 +136,8 @@ const ConfigInfo<int> GFX_STEREO_DEPTH_PERCENTAGE{
// Graphics.Hacks

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"},
64};
const ConfigInfo<bool> GFX_HACK_BBOX_ENABLE{{System::GFX, "Hacks", "BBoxEnable"}, false};
@@ -101,6 +101,7 @@ extern const ConfigInfo<int> GFX_STEREO_DEPTH_PERCENTAGE;
// Graphics.Hacks

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<bool> GFX_HACK_BBOX_ENABLE;
extern const ConfigInfo<bool> GFX_HACK_FORCE_PROGRESSIVE;
@@ -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,
@@ -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)
@@ -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);
@@ -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<u16>(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<u16>(bp.newvalue & 0xFFFF), true);
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF));
@@ -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<int>& rc, bool clear
bool clear_alpha, bool clear_z, u32 color, u32 z)
{
FlushEFBPokes();
InvalidatePeekCache();
FlagPeekCacheAsOutOfDate();
g_renderer->BeginUtilityDrawing();

// Set up uniforms.
@@ -9,10 +9,10 @@
#include <optional>

#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 @@ class FramebufferManager final
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 @@ class FramebufferManager final
std::unique_ptr<AbstractStagingTexture> readback_texture;
std::unique_ptr<AbstractPipeline> copy_pipeline;
std::vector<bool> tiles;
bool out_of_date;
bool valid;
};

@@ -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();
}
}

@@ -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);
@@ -112,6 +112,7 @@ struct VideoConfig final

// Hacks
bool bEFBAccessEnable;
bool bEFBAccessDeferInvalidation;
bool bPerfQueriesEnable;
bool bBBoxEnable;
bool bForceProgressive;

0 comments on commit a218a79

Please sign in to comment.
You can’t perform that action at this time.