FramebufferManager: Implement deferred EFB cache invalidation
This commit is contained in:
parent
6bc4bfd26a
commit
a218a794cb
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue