Large diffs are not rendered by default.

@@ -6,15 +6,16 @@

#include <array>
#include <memory>
#include <optional>

#include "Common/CommonTypes.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/RenderState.h"
#include "VideoCommon/TextureConfig.h"

class AbstractFramebuffer;
class AbstractPipeline;
class AbstractStagingTexture;
class NativeVertexFormat;

enum class EFBReinterpretType
@@ -85,7 +86,9 @@ class FramebufferManager final
// Reads a framebuffer value back from the GPU. This may block if the cache is not current.
u32 PeekEFBColor(u32 x, u32 y);
float PeekEFBDepth(u32 x, u32 y);
void InvalidatePeekCache();
void SetEFBCacheTileSize(u32 size);
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);
@@ -100,6 +103,19 @@ class FramebufferManager final
};
static_assert(std::is_standard_layout<EFBPokeVertex>::value, "EFBPokeVertex is standard-layout");

// EFB cache - for CPU EFB access
// Tiles are ordered left-to-right, then top-to-bottom
struct EFBCacheData
{
std::unique_ptr<AbstractTexture> texture;
std::unique_ptr<AbstractFramebuffer> framebuffer;
std::unique_ptr<AbstractStagingTexture> readback_texture;
std::unique_ptr<AbstractPipeline> copy_pipeline;
std::vector<bool> tiles;
bool out_of_date;
bool valid;
};

bool CreateEFBFramebuffer();
void DestroyEFBFramebuffer();

@@ -118,8 +134,10 @@ class FramebufferManager final
bool CompilePokePipelines();
void DestroyPokePipelines();

bool PopulateColorReadbackTexture();
bool PopulateDepthReadbackTexture();
bool IsUsingTiledEFBCache() const;
bool IsEFBCacheTilePresent(bool depth, u32 x, u32 y, u32* tile_index) const;
MathUtil::Rectangle<int> GetEFBCacheTileRect(u32 tile_index) const;
void PopulateEFBCache(bool depth, u32 tile_index);

void CreatePokeVertices(std::vector<EFBPokeVertex>* destination_list, u32 x, u32 y, float z,
u32 color);
@@ -141,19 +159,11 @@ class FramebufferManager final
// Format conversion shaders
std::array<std::unique_ptr<AbstractPipeline>, 6> m_format_conversion_pipelines;

// EFB readback texture
std::unique_ptr<AbstractTexture> m_color_copy_texture;
std::unique_ptr<AbstractTexture> m_depth_copy_texture;
std::unique_ptr<AbstractFramebuffer> m_color_copy_framebuffer;
std::unique_ptr<AbstractFramebuffer> m_depth_copy_framebuffer;
std::unique_ptr<AbstractPipeline> m_color_copy_pipeline;
std::unique_ptr<AbstractPipeline> m_depth_copy_pipeline;

// CPU-side EFB readback texture
std::unique_ptr<AbstractStagingTexture> m_color_readback_texture;
std::unique_ptr<AbstractStagingTexture> m_depth_readback_texture;
bool m_color_readback_texture_valid = false;
bool m_depth_readback_texture_valid = false;
// EFB cache - for CPU EFB access
u32 m_efb_cache_tile_size = 0;
u32 m_efb_cache_tiles_wide = 0;
EFBCacheData m_efb_color_cache = {};
EFBCacheData m_efb_depth_cache = {};

// EFB clear pipelines
// Indexed by [color_write_enabled][alpha_write_enabled][depth_write_enabled]
@@ -386,6 +386,7 @@ void Renderer::CheckForConfigChanges()
const StereoMode old_stereo = g_ActiveConfig.stereo_mode;
const u32 old_multisamples = g_ActiveConfig.iMultisamples;
const int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
const int old_efb_access_tile_size = g_ActiveConfig.iEFBAccessTileSize;
const bool old_force_filtering = g_ActiveConfig.bForceFiltering;
const bool old_vsync = g_ActiveConfig.bVSyncActive;
const bool old_bbox = g_ActiveConfig.bBBoxEnable;
@@ -395,6 +396,10 @@ void Renderer::CheckForConfigChanges()
// Update texture cache settings with any changed options.
g_texture_cache->OnConfigChanged(g_ActiveConfig);

// EFB tile cache doesn't need to notify the backend.
if (old_efb_access_tile_size != g_ActiveConfig.iEFBAccessTileSize)
g_framebuffer_manager->SetEFBCacheTileSize(std::max(g_ActiveConfig.iEFBAccessTileSize, 0));

// Check for post-processing shader changes. Done up here as it doesn't affect anything outside
// the post-processor. Note that options are applied every frame, so no need to check those.
if (m_post_processor->GetConfig()->GetShader() != g_ActiveConfig.sPostProcessingShader)
@@ -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);
@@ -154,6 +155,7 @@ void VideoConfig::Refresh()
bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING);
iEFBAccessTileSize = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);

bPerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);

@@ -112,6 +112,7 @@ struct VideoConfig final

// Hacks
bool bEFBAccessEnable;
bool bEFBAccessDeferInvalidation;
bool bPerfQueriesEnable;
bool bBBoxEnable;
bool bForceProgressive;
@@ -128,6 +129,7 @@ struct VideoConfig final
bool bEnablePixelLighting;
bool bFastDepthCalc;
bool bVertexRounding;
int iEFBAccessTileSize;
int iLog; // CONF_ bits
int iSaveTargetId; // TODO: Should be dropped

@@ -216,6 +218,7 @@ struct VideoConfig final
bool bSupportsFramebufferFetch; // Used as an alternative to dual-source blend on GLES
bool bSupportsBackgroundCompiling;
bool bSupportsLargePoints;
bool bSupportsPartialDepthCopies;
} backend_info;

// Utility