From e4ea4831e9a3a19c50e8cd1abb42cc8f139bbd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 10 Oct 2023 10:49:58 +0200 Subject: [PATCH] Delete the vertex cache option from the code. --- Core/Config.cpp | 1 - Core/Config.h | 1 - GPU/Common/DrawEngineCommon.cpp | 100 ------------- GPU/Common/DrawEngineCommon.h | 5 - GPU/D3D11/DrawEngineD3D11.cpp | 245 ++---------------------------- GPU/D3D11/DrawEngineD3D11.h | 65 -------- GPU/Directx9/DrawEngineDX9.cpp | 236 +---------------------------- GPU/Directx9/DrawEngineDX9.h | 65 -------- GPU/GLES/DrawEngineGLES.cpp | 4 +- GPU/GPU.h | 6 - GPU/GPUCommonHW.cpp | 6 +- GPU/Vulkan/DrawEngineVulkan.cpp | 258 ++------------------------------ GPU/Vulkan/DrawEngineVulkan.h | 48 ------ Qt/mainwindow.cpp | 2 - Qt/mainwindow.h | 1 - UI/GameSettingsScreen.cpp | 9 -- Windows/MainWindowMenu.cpp | 12 -- Windows/ppsspp.rc | 1 - Windows/resource.h | 1 - headless/Headless.cpp | 1 - libretro/libretro.cpp | 9 -- 21 files changed, 25 insertions(+), 1051 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 5e065e7c39..307c1e3cb8 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -590,7 +590,6 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("AnisotropyLevel", &g_Config.iAnisotropyLevel, 4, CfgFlag::PER_GAME), ConfigSetting("MultiSampleLevel", &g_Config.iMultiSampleLevel, 0, CfgFlag::PER_GAME), // Number of samples is 1 << iMultiSampleLevel - ConfigSetting("VertexDecCache", &g_Config.bVertexCache, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("TextureBackoffCache", &g_Config.bTextureBackoffCache, false, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("VertexDecJit", &g_Config.bVertexDecoderJit, &DefaultCodeGen, CfgFlag::DONT_SAVE | CfgFlag::REPORT), diff --git a/Core/Config.h b/Core/Config.h index 0a12071223..ea25ffdcf9 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -176,7 +176,6 @@ public: float fUITint; float fUISaturation; - bool bVertexCache; bool bTextureBackoffCache; bool bVertexDecoderJit; bool bFullScreen; diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index cbc231608e..8d202f6a6c 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -575,80 +575,6 @@ void DrawEngineCommon::ApplyFramebufferRead(FBOTexState *fboTexState) { gstate_c.Dirty(DIRTY_SHADERBLEND); } -inline u32 ComputeMiniHashRange(const void *ptr, size_t sz) { - // Switch to u32 units, and round up to avoid unaligned accesses. - // Probably doesn't matter if we skip the first few bytes in some cases. - const u32 *p = (const u32 *)(((uintptr_t)ptr + 3) & ~3); - sz >>= 2; - - if (sz > 100) { - size_t step = sz / 4; - u32 hash = 0; - for (size_t i = 0; i < sz; i += step) { - hash += XXH3_64bits(p + i, 100); - } - return hash; - } else { - return p[0] + p[sz - 1]; - } -} - -u32 DrawEngineCommon::ComputeMiniHash() { - u32 fullhash = 0; - const int vertexSize = dec_->GetDecVtxFmt().stride; - const int indexSize = IndexSize(dec_->VertexType()); - - int step; - if (numDrawVerts_ < 3) { - step = 1; - } else if (numDrawVerts_ < 8) { - step = 4; - } else { - step = numDrawVerts_ / 8; - } - for (int i = 0; i < numDrawVerts_; i += step) { - const DeferredVerts &dc = drawVerts_[i]; - fullhash += ComputeMiniHashRange((const u8 *)dc.verts + vertexSize * dc.indexLowerBound, vertexSize * (dc.indexUpperBound - dc.indexLowerBound)); - } - for (int i = 0; i < numDrawInds_; i += step) { - const DeferredInds &di = drawInds_[i]; - if (di.indexType != 0) { - fullhash += ComputeMiniHashRange(di.inds, indexSize * di.vertexCount); - } - } - - return fullhash; -} - -// Cheap bit scrambler from https://nullprogram.com/blog/2018/07/31/ -inline uint32_t lowbias32_r(uint32_t x) { - x ^= x >> 16; - x *= 0x43021123U; - x ^= x >> 15 ^ x >> 30; - x *= 0x1d69e2a5U; - x ^= x >> 16; - return x; -} - -uint32_t DrawEngineCommon::ComputeDrawcallsHash() const { - uint32_t dcid = 0; - for (int i = 0; i < numDrawVerts_; i++) { - u32 dhash = dcid; - dhash = __rotl(dhash ^ (u32)(uintptr_t)drawVerts_[i].verts, 13); - dhash = __rotl(dhash ^ (u32)drawInds_[i].vertexCount, 11); - dcid = lowbias32_r(dhash ^ (u32)drawInds_[i].prim); - } - for (int i = 0; i < numDrawInds_; i++) { - const DeferredInds &di = drawInds_[i]; - u32 dhash = dcid; - if (di.indexType) { - dhash = __rotl(dhash ^ (u32)(uintptr_t)di.inds, 19); - dcid = lowbias32_r(__rotl(dhash ^ (u32)di.indexType, 7)); - } - } - return dcid; -} - int DrawEngineCommon::ComputeNumVertsToDecode() const { int sum = 0; for (int i = 0; i < numDrawVerts_; i++) { @@ -657,32 +583,6 @@ int DrawEngineCommon::ComputeNumVertsToDecode() const { return sum; } -uint64_t DrawEngineCommon::ComputeHash() { - uint64_t fullhash = 0; - const int vertexSize = dec_->GetDecVtxFmt().stride; - - // TODO: Add some caps both for numDrawCalls_ and num verts to check? - // It is really very expensive to check all the vertex data so often. - for (int i = 0; i < numDrawVerts_; i++) { - const DeferredVerts &dv = drawVerts_[i]; - int indexLowerBound = dv.indexLowerBound, indexUpperBound = dv.indexUpperBound; - fullhash += XXH3_64bits((const char *)dv.verts + vertexSize * indexLowerBound, vertexSize * (indexUpperBound - indexLowerBound)); - } - - for (int i = 0; i < numDrawInds_; i++) { - const DeferredInds &di = drawInds_[i]; - if (di.indexType != 0) { - int indexSize = IndexSize(di.indexType << GE_VTYPE_IDX_SHIFT); - // Hm, we will miss some indices when combining above, but meh, it should be fine. - fullhash += XXH3_64bits((const char *)di.inds, indexSize * di.vertexCount); - } - } - - // this looks utterly broken?? - // fullhash += XXH3_64bits(&drawCalls_[0].uvScale, sizeof(drawCalls_[0].uvScale) * numDrawCalls_); - return fullhash; -} - int DrawEngineCommon::ExtendNonIndexedPrim(const uint32_t *cmd, const uint32_t *stall, u32 vertTypeID, bool clockwise, int *bytesRead, bool isTriangle) { const uint32_t *start = cmd; int prevDrawVerts = numDrawVerts_ - 1; diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 5827c958f4..e9e8870ef3 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -159,10 +159,6 @@ protected: // Preprocessing for spline/bezier u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize = nullptr); - // Utility for vertex caching - u32 ComputeMiniHash(); - uint64_t ComputeHash(); - int ComputeNumVertsToDecode() const; void ApplyFramebufferRead(FBOTexState *fboTexState); @@ -271,7 +267,6 @@ protected: int numDrawInds_ = 0; int vertexCountInDrawCalls_ = 0; - int decimationCounter_ = 0; int decodeVertsCounter_ = 0; int decodeIndsCounter_ = 0; diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index f04385bb6f..778569ed3f 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -53,9 +53,6 @@ const D3D11_PRIMITIVE_TOPOLOGY d3d11prim[8] = { D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Need expansion - though we could do it with geom shaders in most cases }; -#define VERTEXCACHE_DECIMATION_INTERVAL 17 - -enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; enum { VERTEX_PUSH_SIZE = 1024 * 1024 * 16, INDEX_PUSH_SIZE = 1024 * 1024 * 4, @@ -73,7 +70,6 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, : draw_(draw), device_(device), context_(context), - vai_(256), inputLayoutMap_(32), blendCache_(32), blendCache1_(32), @@ -84,7 +80,6 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, decOptions_.expandAllWeightsToFloat = true; decOptions_.expand8BitNormalsToFloat = true; - decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; // Allocate nicely aligned memory. Maybe graphics drivers will // appreciate it. // All this is a LOT of memory, need to see if we can cut down somehow. @@ -111,13 +106,6 @@ void DrawEngineD3D11::InitDeviceObjects() { draw_->SetInvalidationCallback(std::bind(&DrawEngineD3D11::Invalidate, this, std::placeholders::_1)); } -void DrawEngineD3D11::ClearTrackedVertexArrays() { - vai_.Iterate([&](uint32_t hash, VertexArrayInfoD3D11 *vai){ - delete vai; - }); - vai_.Clear(); -} - void DrawEngineD3D11::ClearInputLayoutMap() { inputLayoutMap_.Iterate([&](const InputLayoutKey &key, ID3D11InputLayout *il) { if (il) @@ -259,69 +247,13 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade } } -void DrawEngineD3D11::MarkUnreliable(VertexArrayInfoD3D11 *vai) { - vai->status = VertexArrayInfoD3D11::VAI_UNRELIABLE; - if (vai->vbo) { - vai->vbo->Release(); - vai->vbo = nullptr; - } - if (vai->ebo) { - vai->ebo->Release(); - vai->ebo = nullptr; - } -} - void DrawEngineD3D11::BeginFrame() { pushVerts_->Reset(); pushInds_->Reset(); - gpuStats.numTrackedVertexArrays = (int)vai_.size(); - - if (--decimationCounter_ <= 0) { - decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - const int threshold = gpuStats.numFlips - VAI_KILL_AGE; - const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; - int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; - vai_.Iterate([&](uint32_t hash, VertexArrayInfoD3D11 *vai){ - bool kill; - if (vai->status == VertexArrayInfoD3D11::VAI_UNRELIABLE) { - // We limit killing unreliable so we don't rehash too often. - kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; - } else { - kill = vai->lastFrame < threshold; - } - if (kill) { - delete vai; - vai_.Remove(hash); - } - }); - vai_.Maintain(); - - // Enable if you want to see vertex decoders in the log output. Need a better way. -#if 0 - char buffer[16384]; - for (std::map::iterator dec = decoderMap_.begin(); dec != decoderMap_.end(); ++dec) { - char *ptr = buffer; - ptr += dec->second->ToString(ptr); - // *ptr++ = '\n'; - NOTICE_LOG(G3D, buffer); - } -#endif - lastRenderStepId_ = -1; } -VertexArrayInfoD3D11::~VertexArrayInfoD3D11() { - if (vbo) - vbo->Release(); - if (ebo) - ebo->Release(); -} - // In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor. void DrawEngineD3D11::Invalidate(InvalidationCallbackFlags flags) { if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) { @@ -354,175 +286,16 @@ void DrawEngineD3D11::DoFlush() { ID3D11Buffer *vb_ = nullptr; ID3D11Buffer *ib_ = nullptr; - int vertexCount = 0; - int maxIndex = 0; - bool useElements = true; - - // Cannot cache vertex data with morph enabled. - bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. - if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) - useCache = false; - - if (useCache) { - // getUVGenMode can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 - u32 dcid = ComputeDrawcallsHash() ^ gstate.getUVGenMode(); - - VertexArrayInfoD3D11 *vai; - if (!vai_.Get(dcid, &vai)) { - vai = new VertexArrayInfoD3D11(); - vai_.Insert(dcid, vai); - } - - switch (vai->status) { - case VertexArrayInfoD3D11::VAI_NEW: - { - // Haven't seen this one before. - uint64_t dataHash = ComputeHash(); - vai->hash = dataHash; - vai->minihash = ComputeMiniHash(); - vai->status = VertexArrayInfoD3D11::VAI_HASHING; - vai->drawsUntilNextFullHash = 0; - DecodeVerts(decoded_); // writes to indexGen - DecodeInds(); - vai->numVerts = indexGen.VertexCount(); - vai->prim = indexGen.Prim(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAI11_FLAG_VERTEXFULLALPHA : 0; - goto rotateVBO; - } - - // Hashing - still gaining confidence about the buffer. - // But if we get this far it's likely to be worth creating a vertex buffer. - case VertexArrayInfoD3D11::VAI_HASHING: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - if (vai->drawsUntilNextFullHash == 0) { - // Let's try to skip a full hash if mini would fail. - const u32 newMiniHash = ComputeMiniHash(); - uint64_t newHash = vai->hash; - if (newMiniHash == vai->minihash) { - newHash = ComputeHash(); - } - if (newMiniHash != vai->minihash || newHash != vai->hash) { - MarkUnreliable(vai); - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - if (vai->numVerts > 64) { - // exponential backoff up to 16 draws, then every 24 - vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); - } else { - // Lower numbers seem much more likely to change. - vai->drawsUntilNextFullHash = 0; - } - // TODO: tweak - //if (vai->numFrames > 1000) { - // vai->status = VertexArrayInfo::VAI_RELIABLE; - //} - } else { - vai->drawsUntilNextFullHash--; - u32 newMiniHash = ComputeMiniHash(); - if (newMiniHash != vai->minihash) { - MarkUnreliable(vai); - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - } - - if (vai->vbo == 0) { - DecodeVerts(decoded_); - DecodeInds(); - vai->numVerts = indexGen.VertexCount(); - vai->prim = indexGen.Prim(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAI11_FLAG_VERTEXFULLALPHA : 0; - useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; - if (!useElements && indexGen.PureCount()) { - vai->numVerts = indexGen.PureCount(); - } - - _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); - - // TODO: Combine these two into one buffer? - u32 size = dec_->GetDecVtxFmt().stride * MaxIndex(); - D3D11_BUFFER_DESC desc{ size, D3D11_USAGE_IMMUTABLE, D3D11_BIND_VERTEX_BUFFER, 0 }; - D3D11_SUBRESOURCE_DATA data{ decoded_ }; - ASSERT_SUCCESS(device_->CreateBuffer(&desc, &data, &vai->vbo)); - if (useElements) { - u32 size = sizeof(short) * indexGen.VertexCount(); - D3D11_BUFFER_DESC desc{ size, D3D11_USAGE_IMMUTABLE, D3D11_BIND_INDEX_BUFFER, 0 }; - D3D11_SUBRESOURCE_DATA data{ decIndex_ }; - ASSERT_SUCCESS(device_->CreateBuffer(&desc, &data, &vai->ebo)); - } else { - vai->ebo = 0; - } - } else { - gpuStats.numCachedDrawCalls++; - useElements = vai->ebo ? true : false; - gpuStats.numCachedVertsDrawn += vai->numVerts; - gstate_c.vertexFullAlpha = vai->flags & VAI11_FLAG_VERTEXFULLALPHA; - } - vb_ = vai->vbo; - ib_ = vai->ebo; - vertexCount = vai->numVerts; - maxIndex = vai->maxIndex; - prim = static_cast(vai->prim); - break; - } - - // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. - case VertexArrayInfoD3D11::VAI_RELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - gpuStats.numCachedDrawCalls++; - gpuStats.numCachedVertsDrawn += vai->numVerts; - vb_ = vai->vbo; - ib_ = vai->ebo; - - vertexCount = vai->numVerts; - - maxIndex = vai->maxIndex; - prim = static_cast(vai->prim); - - gstate_c.vertexFullAlpha = vai->flags & VAI11_FLAG_VERTEXFULLALPHA; - break; - } - - case VertexArrayInfoD3D11::VAI_UNRELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - } - - vai->lastFrame = gpuStats.numFlips; - } else { - DecodeVerts(decoded_); - DecodeInds(); -rotateVBO: - gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); - useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; - vertexCount = indexGen.VertexCount(); - maxIndex = MaxIndex(); - if (!useElements && indexGen.PureCount()) { - vertexCount = indexGen.PureCount(); - } - prim = indexGen.Prim(); + DecodeVerts(decoded_); + DecodeInds(); + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); + bool useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; + int vertexCount = indexGen.VertexCount(); + int maxIndex = MaxIndex(); + if (!useElements && indexGen.PureCount()) { + vertexCount = indexGen.PureCount(); } + prim = indexGen.Prim(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 2b1a9fbf79..9f365ab247 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -38,65 +38,6 @@ class ShaderManagerD3D11; class TextureCacheD3D11; class FramebufferManagerD3D11; -// States transitions: -// On creation: DRAWN_NEW -// DRAWN_NEW -> DRAWN_HASHING -// DRAWN_HASHING -> DRAWN_RELIABLE -// DRAWN_HASHING -> DRAWN_UNRELIABLE -// DRAWN_ONCE -> UNRELIABLE -// DRAWN_RELIABLE -> DRAWN_SAFE -// UNRELIABLE -> death -// DRAWN_ONCE -> death -// DRAWN_RELIABLE -> death - -enum { - VAI11_FLAG_VERTEXFULLALPHA = 1, -}; - -// Try to keep this POD. -class VertexArrayInfoD3D11 { -public: - VertexArrayInfoD3D11() { - status = VAI_NEW; - vbo = 0; - ebo = 0; - prim = GE_PRIM_INVALID; - numDraws = 0; - numFrames = 0; - lastFrame = gpuStats.numFlips; - numVerts = 0; - drawsUntilNextFullHash = 0; - flags = 0; - } - ~VertexArrayInfoD3D11(); - - enum Status : uint8_t { - VAI_NEW, - VAI_HASHING, - VAI_RELIABLE, // cache, don't hash - VAI_UNRELIABLE, // never cache - }; - - uint64_t hash; - u32 minihash; - - ID3D11Buffer *vbo; - ID3D11Buffer *ebo; - - // Precalculated parameter for drawRangeElements - u16 numVerts; - u16 maxIndex; - s8 prim; - Status status; - - // ID information - int numDraws; - int numFrames; - int lastFrame; // So that we can forget. - u16 drawsUntilNextFullHash; - u8 flags; -}; - class TessellationDataTransferD3D11 : public TessellationDataTransfer { private: ID3D11DeviceContext *context_; @@ -155,8 +96,6 @@ public: Flush(); } - void ClearTrackedVertexArrays() override; - void NotifyConfigChanged() override; void ClearInputLayoutMap(); @@ -171,16 +110,12 @@ private: ID3D11InputLayout *SetupDecFmtForDraw(D3D11VertexShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt); - void MarkUnreliable(VertexArrayInfoD3D11 *vai); - Draw::DrawContext *draw_; // Used for framebuffer related things exclusively. ID3D11Device *device_; ID3D11Device1 *device1_; ID3D11DeviceContext *context_; ID3D11DeviceContext1 *context1_; - PrehashMap vai_; - struct InputLayoutKey { D3D11VertexShader *vshader; u32 decFmtId; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 283ccd375e..3575a6dbb1 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -72,10 +72,6 @@ enum { TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex) }; -#define VERTEXCACHE_DECIMATION_INTERVAL 17 - -enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; - static const D3DVERTEXELEMENT9 TransformedVertexElements[] = { { 0, offsetof(TransformedVertex, pos), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, offsetof(TransformedVertex, uv), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, @@ -85,13 +81,11 @@ static const D3DVERTEXELEMENT9 TransformedVertexElements[] = { D3DDECL_END() }; -DrawEngineDX9::DrawEngineDX9(Draw::DrawContext *draw) : draw_(draw), vai_(256), vertexDeclMap_(64) { +DrawEngineDX9::DrawEngineDX9(Draw::DrawContext *draw) : draw_(draw), vertexDeclMap_(64) { device_ = (LPDIRECT3DDEVICE9)draw->GetNativeObject(Draw::NativeObject::DEVICE); decOptions_.expandAllWeightsToFloat = true; decOptions_.expand8BitNormalsToFloat = true; - decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - indexGen.Setup(decIndex_); InitDeviceObjects(); @@ -227,80 +221,11 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(const DecVtxForma } } -void DrawEngineDX9::MarkUnreliable(VertexArrayInfoDX9 *vai) { - vai->status = VertexArrayInfoDX9::VAI_UNRELIABLE; - if (vai->vbo) { - vai->vbo->Release(); - vai->vbo = nullptr; - } - if (vai->ebo) { - vai->ebo->Release(); - vai->ebo = nullptr; - } -} - -void DrawEngineDX9::ClearTrackedVertexArrays() { - vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { - delete vai; - }); - vai_.Clear(); -} - -void DrawEngineDX9::DecimateTrackedVertexArrays() { - if (--decimationCounter_ <= 0) { - decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - const int threshold = gpuStats.numFlips - VAI_KILL_AGE; - const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; - int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; - vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { - bool kill; - if (vai->status == VertexArrayInfoDX9::VAI_UNRELIABLE) { - // We limit killing unreliable so we don't rehash too often. - kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; - } else { - kill = vai->lastFrame < threshold; - } - if (kill) { - delete vai; - vai_.Remove(hash); - } - }); - vai_.Maintain(); - - // Enable if you want to see vertex decoders in the log output. Need a better way. -#if 0 - char buffer[16384]; - for (std::map::iterator dec = decoderMap_.begin(); dec != decoderMap_.end(); ++dec) { - char *ptr = buffer; - ptr += dec->second->ToString(ptr); - // *ptr++ = '\n'; - NOTICE_LOG(G3D, buffer); - } -#endif -} - -VertexArrayInfoDX9::~VertexArrayInfoDX9() { - if (vbo) { - vbo->Release(); - } - if (ebo) { - ebo->Release(); - } -} - static uint32_t SwapRB(uint32_t c) { return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000); } void DrawEngineDX9::BeginFrame() { - gpuStats.numTrackedVertexArrays = (int)vai_.size(); - - DecimateTrackedVertexArrays(); - lastRenderStepId_ = -1; } @@ -336,166 +261,9 @@ void DrawEngineDX9::DoFlush() { int vertexCount = 0; int maxIndex = 0; bool useElements = true; - - // Cannot cache vertex data with morph enabled. - bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. - if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) - useCache = false; - - if (useCache) { - // getUVGenMode can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 - u32 dcid = ComputeDrawcallsHash() ^ gstate.getUVGenMode(); - VertexArrayInfoDX9 *vai; - if (!vai_.Get(dcid, &vai)) { - vai = new VertexArrayInfoDX9(); - vai_.Insert(dcid, vai); - } - - switch (vai->status) { - case VertexArrayInfoDX9::VAI_NEW: - { - // Haven't seen this one before. - uint64_t dataHash = ComputeHash(); - vai->hash = dataHash; - vai->minihash = ComputeMiniHash(); - vai->status = VertexArrayInfoDX9::VAI_HASHING; - vai->drawsUntilNextFullHash = 0; - DecodeVerts(decoded_); // writes to indexGen - DecodeInds(); - vai->numVerts = indexGen.VertexCount(); - vai->prim = indexGen.Prim(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAI_FLAG_VERTEXFULLALPHA : 0; - - goto rotateVBO; - } - - // Hashing - still gaining confidence about the buffer. - // But if we get this far it's likely to be worth creating a vertex buffer. - case VertexArrayInfoDX9::VAI_HASHING: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - if (vai->drawsUntilNextFullHash == 0) { - // Let's try to skip a full hash if mini would fail. - const u32 newMiniHash = ComputeMiniHash(); - uint64_t newHash = vai->hash; - if (newMiniHash == vai->minihash) { - newHash = ComputeHash(); - } - if (newMiniHash != vai->minihash || newHash != vai->hash) { - MarkUnreliable(vai); - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - if (vai->numVerts > 64) { - // exponential backoff up to 16 draws, then every 24 - vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); - } else { - // Lower numbers seem much more likely to change. - vai->drawsUntilNextFullHash = 0; - } - // TODO: tweak - //if (vai->numFrames > 1000) { - // vai->status = VertexArrayInfo::VAI_RELIABLE; - //} - } else { - vai->drawsUntilNextFullHash--; - u32 newMiniHash = ComputeMiniHash(); - if (newMiniHash != vai->minihash) { - MarkUnreliable(vai); - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - } - - if (vai->vbo == 0) { - DecodeVerts(decoded_); - DecodeInds(); - vai->numVerts = indexGen.VertexCount(); - vai->prim = indexGen.Prim(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAI_FLAG_VERTEXFULLALPHA : 0; - useElements = !indexGen.SeenOnlyPurePrims(); - if (!useElements && indexGen.PureCount()) { - vai->numVerts = indexGen.PureCount(); - } - - _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); - - void * pVb; - u32 size = dec_->GetDecVtxFmt().stride * MaxIndex(); - device_->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &vai->vbo, NULL); - vai->vbo->Lock(0, size, &pVb, 0); - memcpy(pVb, decoded_, size); - vai->vbo->Unlock(); - if (useElements) { - void * pIb; - u32 size = sizeof(short) * indexGen.VertexCount(); - device_->CreateIndexBuffer(size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &vai->ebo, NULL); - vai->ebo->Lock(0, size, &pIb, 0); - memcpy(pIb, decIndex_, size); - vai->ebo->Unlock(); - } else { - vai->ebo = 0; - } - } else { - gpuStats.numCachedDrawCalls++; - useElements = vai->ebo ? true : false; - gpuStats.numCachedVertsDrawn += vai->numVerts; - gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; - } - vb_ = vai->vbo; - ib_ = vai->ebo; - vertexCount = vai->numVerts; - maxIndex = vai->maxIndex; - prim = static_cast(vai->prim); - break; - } - - // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. - case VertexArrayInfoDX9::VAI_RELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - gpuStats.numCachedDrawCalls++; - gpuStats.numCachedVertsDrawn += vai->numVerts; - vb_ = vai->vbo; - ib_ = vai->ebo; - - vertexCount = vai->numVerts; - - maxIndex = vai->maxIndex; - prim = static_cast(vai->prim); - - gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA; - break; - } - - case VertexArrayInfoDX9::VAI_UNRELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - DecodeVerts(decoded_); - DecodeInds(); - goto rotateVBO; - } - } - - vai->lastFrame = gpuStats.numFlips; - } else { + { DecodeVerts(decoded_); DecodeInds(); -rotateVBO: gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); useElements = !indexGen.SeenOnlyPurePrims(); vertexCount = indexGen.VertexCount(); diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index a527523b71..14a3803989 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -35,65 +35,6 @@ class ShaderManagerDX9; class TextureCacheDX9; class FramebufferManagerDX9; -// States transitions: -// On creation: DRAWN_NEW -// DRAWN_NEW -> DRAWN_HASHING -// DRAWN_HASHING -> DRAWN_RELIABLE -// DRAWN_HASHING -> DRAWN_UNRELIABLE -// DRAWN_ONCE -> UNRELIABLE -// DRAWN_RELIABLE -> DRAWN_SAFE -// UNRELIABLE -> death -// DRAWN_ONCE -> death -// DRAWN_RELIABLE -> death - -enum { - VAI_FLAG_VERTEXFULLALPHA = 1, -}; - -// Try to keep this POD. -class VertexArrayInfoDX9 { -public: - VertexArrayInfoDX9() { - status = VAI_NEW; - vbo = 0; - ebo = 0; - prim = GE_PRIM_INVALID; - numDraws = 0; - numFrames = 0; - lastFrame = gpuStats.numFlips; - numVerts = 0; - drawsUntilNextFullHash = 0; - flags = 0; - } - ~VertexArrayInfoDX9(); - - enum Status : uint8_t { - VAI_NEW, - VAI_HASHING, - VAI_RELIABLE, // cache, don't hash - VAI_UNRELIABLE, // never cache - }; - - uint64_t hash; - u32 minihash; - - LPDIRECT3DVERTEXBUFFER9 vbo; - LPDIRECT3DINDEXBUFFER9 ebo; - - // Precalculated parameter for drawRangeElements - u16 numVerts; - u16 maxIndex; - s8 prim; - Status status; - - // ID information - int numDraws; - int numFrames; - int lastFrame; // So that we can forget. - u16 drawsUntilNextFullHash; - u8 flags; -}; - class TessellationDataTransferDX9 : public TessellationDataTransfer { public: TessellationDataTransferDX9() {} @@ -122,8 +63,6 @@ public: void InitDeviceObjects(); void DestroyDeviceObjects(); - void ClearTrackedVertexArrays() override; - void BeginFrame(); // So that this can be inlined @@ -148,7 +87,6 @@ public: protected: // Not currently supported. bool UpdateUseHWTessellation(bool enable) const override { return false; } - void DecimateTrackedVertexArrays(); private: void Invalidate(InvalidationCallbackFlags flags); @@ -159,12 +97,9 @@ private: IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(const DecVtxFormat &decFmt, u32 pspFmt); - void MarkUnreliable(VertexArrayInfoDX9 *vai); - LPDIRECT3DDEVICE9 device_ = nullptr; Draw::DrawContext *draw_; - PrehashMap vai_; DenseHashMap vertexDeclMap_; // SimpleVertex diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index b6f5f8a548..598a41546a 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -44,7 +44,7 @@ #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/GPU_GLES.h" -const GLuint glprim[8] = { +static const GLuint glprim[8] = { // Points, which are expanded to triangles. GL_TRIANGLES, // Lines and line strips, which are also expanded to triangles. @@ -149,8 +149,6 @@ void DrawEngineGLES::ClearInputLayoutMap() { } void DrawEngineGLES::BeginFrame() { - gpuStats.numTrackedVertexArrays = 0; - FrameData &frameData = frameData_[render_->GetCurFrame()]; render_->BeginPushBuffer(frameData.pushIndex); render_->BeginPushBuffer(frameData.pushVertex); diff --git a/GPU/GPU.h b/GPU/GPU.h index 843a89f60e..cbd148078c 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -78,11 +78,8 @@ struct GPUStatistics { numVertexDecodes = 0; numDrawSyncs = 0; numListSyncs = 0; - numCachedDrawCalls = 0; numVertsSubmitted = 0; - numCachedVertsDrawn = 0; numUncachedVertsDrawn = 0; - numTrackedVertexArrays = 0; numTextureInvalidations = 0; numTextureInvalidationsByFramebuffer = 0; numTexturesHashed = 0; @@ -115,14 +112,11 @@ struct GPUStatistics { int numVertexDecodes; int numDrawSyncs; int numListSyncs; - int numCachedDrawCalls; int numFlushes; int numBBOXJumps; int numPlaneUpdates; int numVertsSubmitted; - int numCachedVertsDrawn; int numUncachedVertsDrawn; - int numTrackedVertexArrays; int numTextureInvalidations; int numTextureInvalidationsByFramebuffer; int numTexturesHashed; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index b08839ac77..4491d08369 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1685,8 +1685,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { return snprintf(buffer, size, "DL processing time: %0.2f ms, %d drawsync, %d listsync\n" "Draw: %d (%d dec), flushes %d, clears %d, bbox jumps %d (%d updates)\n" - "Cached draws: %d (tracked: %d)\n" - "Vertices: %d cached: %d uncached: %d\n" + "Vertices: %d drawn: %d\n" "FBOs active: %d (evaluations: %d)\n" "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" "readbacks %d (%d non-block), uploads %d, depal %d\n" @@ -1703,10 +1702,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { gpuStats.numClears, gpuStats.numBBOXJumps, gpuStats.numPlaneUpdates, - gpuStats.numCachedDrawCalls, - gpuStats.numTrackedVertexArrays, gpuStats.numVertsSubmitted, - gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, (int)framebufferManager_->NumVFBs(), gpuStats.numFramebufferEvaluations, diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 2fd336155e..37dabe5428 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -54,20 +54,12 @@ using namespace PPSSPP_VK; -enum { - VERTEX_CACHE_SIZE = 8192 * 1024 -}; - -#define VERTEXCACHE_DECIMATION_INTERVAL 17 - -enum { VAI_KILL_AGE = 120, VAI_UNRELIABLE_KILL_AGE = 240, VAI_UNRELIABLE_KILL_MAX = 4 }; - enum { TRANSFORMED_VERTEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * sizeof(TransformedVertex) }; DrawEngineVulkan::DrawEngineVulkan(Draw::DrawContext *draw) - : draw_(draw), vai_(1024) { + : draw_(draw) { decOptions_.expandAllWeightsToFloat = false; decOptions_.expand8BitNormalsToFloat = false; #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) @@ -117,8 +109,6 @@ void DrawEngineVulkan::InitDeviceObjects() { res = vkCreateSampler(device, &samp, nullptr, &nullSampler_); _dbg_assert_(VK_SUCCESS == res); - vertexCache_ = new VulkanPushBuffer(vulkan, "pushVertexCache", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan); tessDataTransfer = tessDataTransferVulkan; @@ -163,18 +153,8 @@ void DrawEngineVulkan::DestroyDeviceObjects() { vulkan->Delete().QueueDeleteSampler(samplerSecondaryLinear_); if (nullSampler_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(nullSampler_); - renderManager->DestroyPipelineLayout(pipelineLayout_); - if (vertexCache_) { - vertexCache_->Destroy(vulkan); - delete vertexCache_; - vertexCache_ = nullptr; - } - // Need to clear this to get rid of all remaining references to the dead buffers. - vai_.Iterate([](uint32_t hash, VertexArrayInfoVulkan *vai) { - delete vai; - }); - vai_.Clear(); + renderManager->DestroyPipelineLayout(pipelineLayout_); } void DrawEngineVulkan::DeviceLost() { @@ -189,8 +169,6 @@ void DrawEngineVulkan::DeviceRestore(Draw::DrawContext *draw) { } void DrawEngineVulkan::BeginFrame() { - gpuStats.numTrackedVertexArrays = (int)vai_.size(); - lastPipeline_ = nullptr; // pushUBO is the thin3d push pool, don't need to BeginFrame again. @@ -200,54 +178,11 @@ void DrawEngineVulkan::BeginFrame() { tessDataTransferVulkan->SetPushPool(pushUBO_); DirtyAllUBOs(); - - // First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it, - // if growing the buffer is needed. Doing it this way will reduce fragmentation if more than one buffer - // needs to grow in the same frame. The state where many buffers are reset can also be used to - // defragment memory. - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - - // Wipe the vertex cache if it's grown too large. - if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) { - vertexCache_->Destroy(vulkan); - delete vertexCache_; // orphans the buffers, they'll get deleted once no longer used by an in-flight frame. - vertexCache_ = new VulkanPushBuffer(vulkan, "vertexCacheR", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) { - delete vai; - }); - vai_.Clear(); - } - - vertexCache_->BeginNoReset(); - - if (--decimationCounter_ <= 0) { - decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL; - - const int threshold = gpuStats.numFlips - VAI_KILL_AGE; - const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; - int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; - vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) { - bool kill; - if (vai->status == VertexArrayInfoVulkan::VAI_UNRELIABLE) { - // We limit killing unreliable so we don't rehash too often. - kill = vai->lastFrame < unreliableThreshold && --unreliableLeft >= 0; - } else { - kill = vai->lastFrame < threshold; - } - if (kill) { - // This is actually quite safe. - vai_.Remove(hash); - delete vai; - } - }); - } - vai_.Maintain(); } void DrawEngineVulkan::EndFrame() { stats_.pushVertexSpaceUsed = (int)pushVertex_->GetUsedThisFrame(); stats_.pushIndexSpaceUsed = (int)pushIndex_->GetUsedThisFrame(); - vertexCache_->End(); } void DrawEngineVulkan::DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf) { @@ -285,12 +220,6 @@ void DrawEngineVulkan::DirtyAllUBOs() { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } -void MarkUnreliable(VertexArrayInfoVulkan *vai) { - vai->status = VertexArrayInfoVulkan::VAI_UNRELIABLE; - // TODO: If we change to a real allocator, free the data here. - // For now we just leave it in the pushbuffer. -} - void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) { if (flags & InvalidationCallbackFlags::COMMAND_BUFFER_STATE) { // Nothing here anymore (removed the "frame descriptor set" @@ -305,158 +234,6 @@ void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) { } } -bool DrawEngineVulkan::VertexCacheLookup(int &vertexCount, GEPrimitiveType &prim, VkBuffer &vbuf, uint32_t &vbOffset, VkBuffer &ibuf, uint32_t &ibOffset, bool &useElements, bool forceIndexed) { - // getUVGenMode can have an effect on which UV decoder we need to use! And hence what the decoded data will look like. See #9263 - // u32 dcid = (u32)XXH3_64bits(&drawCalls_, sizeof(DeferredDrawCall) * numDrawCalls_) ^ gstate.getUVGenMode(); - u32 dcid = ComputeDrawcallsHash() ^ gstate.getUVGenMode(); - - PROFILE_THIS_SCOPE("vcache"); - VertexArrayInfoVulkan *vai; - if (!vai_.Get(dcid, &vai)) { - vai = new VertexArrayInfoVulkan(); - vai_.Insert(dcid, vai); - } - - switch (vai->status) { - case VertexArrayInfoVulkan::VAI_NEW: - { - // Haven't seen this one before. We don't actually upload the vertex data yet. - uint64_t dataHash = ComputeHash(); - vai->hash = dataHash; - vai->minihash = ComputeMiniHash(); - vai->status = VertexArrayInfoVulkan::VAI_HASHING; - vai->drawsUntilNextFullHash = 0; - DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); - DecodeInds(); - vai->numVerts = indexGen.VertexCount(); - vai->prim = indexGen.Prim(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAIVULKAN_FLAG_VERTEXFULLALPHA : 0; - return true; - } - - // Hashing - still gaining confidence about the buffer. - // But if we get this far it's likely to be worth uploading the data. - case VertexArrayInfoVulkan::VAI_HASHING: - { - PROFILE_THIS_SCOPE("vcachehash"); - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - if (vai->drawsUntilNextFullHash == 0) { - // Let's try to skip a full hash if mini would fail. - const u32 newMiniHash = ComputeMiniHash(); - uint64_t newHash = vai->hash; - if (newMiniHash == vai->minihash) { - newHash = ComputeHash(); - } - if (newMiniHash != vai->minihash || newHash != vai->hash) { - MarkUnreliable(vai); - DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); - DecodeInds(); - return true; - } - if (vai->numVerts > 64) { - // exponential backoff up to 16 draws, then every 24 - vai->drawsUntilNextFullHash = std::min(24, vai->numFrames); - } else { - // Lower numbers seem much more likely to change. - vai->drawsUntilNextFullHash = 0; - } - // TODO: tweak - //if (vai->numFrames > 1000) { - // vai->status = VertexArrayInfo::VAI_RELIABLE; - //} - } else { - vai->drawsUntilNextFullHash--; - u32 newMiniHash = ComputeMiniHash(); - if (newMiniHash != vai->minihash) { - MarkUnreliable(vai); - DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); - DecodeInds(); - return true; - } - } - - if (!vai->vb) { - // Directly push to the vertex cache. - DecodeVertsToPushBuffer(vertexCache_, &vai->vbOffset, &vai->vb); - DecodeInds(); - _dbg_assert_msg_(gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching."); - vai->numVerts = indexGen.VertexCount(); - vai->maxIndex = MaxIndex(); - vai->flags = gstate_c.vertexFullAlpha ? VAIVULKAN_FLAG_VERTEXFULLALPHA : 0; - if (forceIndexed) { - vai->prim = indexGen.GeneralPrim(); - useElements = true; - } else { - vai->prim = indexGen.Prim(); - useElements = !indexGen.SeenOnlyPurePrims(); - if (!useElements && indexGen.PureCount()) { - vai->numVerts = indexGen.PureCount(); - } - } - - if (useElements) { - u32 size = sizeof(uint16_t) * indexGen.VertexCount(); - void *dest = vertexCache_->Allocate(size, 4, &vai->ib, &vai->ibOffset); - memcpy(dest, decIndex_, size); - } else { - vai->ib = VK_NULL_HANDLE; - vai->ibOffset = 0; - } - } else { - gpuStats.numCachedDrawCalls++; - useElements = vai->ib ? true : false; - gpuStats.numCachedVertsDrawn += vai->numVerts; - gstate_c.vertexFullAlpha = vai->flags & VAIVULKAN_FLAG_VERTEXFULLALPHA; - } - vbuf = vai->vb; - ibuf = vai->ib; - vbOffset = vai->vbOffset; - ibOffset = vai->ibOffset; - vertexCount = vai->numVerts; - prim = static_cast(vai->prim); - break; - } - - // Reliable - we don't even bother hashing anymore. Right now we don't go here until after a very long time. - case VertexArrayInfoVulkan::VAI_RELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - gpuStats.numCachedDrawCalls++; - gpuStats.numCachedVertsDrawn += vai->numVerts; - vbuf = vai->vb; - ibuf = vai->ib; - vbOffset = vai->vbOffset; - ibOffset = vai->ibOffset; - vertexCount = vai->numVerts; - prim = static_cast(vai->prim); - - gstate_c.vertexFullAlpha = vai->flags & VAIVULKAN_FLAG_VERTEXFULLALPHA; - break; - } - - case VertexArrayInfoVulkan::VAI_UNRELIABLE: - { - vai->numDraws++; - if (vai->lastFrame != gpuStats.numFlips) { - vai->numFrames++; - } - DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); - DecodeInds(); - return true; - } - default: - break; - } - return false; -} - // The inline wrapper in the header checks for numDrawCalls_ == 0 void DrawEngineVulkan::DoFlush() { VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); @@ -490,32 +267,21 @@ void DrawEngineVulkan::DoFlush() { if (useHWTransform) { int vertexCount = 0; bool useElements = true; - - // Cannot cache vertex data with morph enabled. - bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); - // Also avoid caching when software skinning. VkBuffer vbuf = VK_NULL_HANDLE; VkBuffer ibuf = VK_NULL_HANDLE; - if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { - useCache = false; - } bool useIndexGen = true; - if (useCache) { - useIndexGen = VertexCacheLookup(vertexCount, prim, vbuf, vbOffset, ibuf, ibOffset, useElements, forceIndexed); + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. + DecodeVerts(decoded_); + VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); + memcpy(dest, decoded_, size); } else { - if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { - // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. - DecodeVerts(decoded_); - VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; - u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); - memcpy(dest, decoded_, size); - } else { - // Decode directly into the pushbuffer - DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); - } - DecodeInds(); - gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); + // Decode directly into the pushbuffer + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); } + DecodeInds(); + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); if (useIndexGen) { vertexCount = indexGen.VertexCount(); diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 9e883b0121..491c119b67 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -70,49 +70,6 @@ struct DrawEngineVulkanStats { int pushIndexSpaceUsed; }; -enum { - VAIVULKAN_FLAG_VERTEXFULLALPHA = 1, -}; - -// Try to keep this POD. -class VertexArrayInfoVulkan { -public: - VertexArrayInfoVulkan() { - lastFrame = gpuStats.numFlips; - } - // No destructor needed - we always fully wipe. - - enum VAIStatus : uint8_t { - VAI_NEW, - VAI_HASHING, - VAI_RELIABLE, // cache, don't hash - VAI_UNRELIABLE, // never cache - }; - - uint64_t hash = 0; - u32 minihash = 0; - - // These will probably always be the same, but whatever. - VkBuffer vb = VK_NULL_HANDLE; - VkBuffer ib = VK_NULL_HANDLE; - // Offsets into the cache buffer. - uint32_t vbOffset = 0; - uint32_t ibOffset = 0; - - // Precalculated parameter for vkDrawIndexed - u16 numVerts = 0; - u16 maxIndex = 0; - s8 prim = GE_PRIM_INVALID; - VAIStatus status = VAI_NEW; - - // ID information - int numDraws = 0; - int numFrames = 0; - int lastFrame; // So that we can forget. - u16 drawsUntilNextFullHash = 0; - u8 flags = 0; -}; - class VulkanRenderManager; class TessellationDataTransferVulkan : public TessellationDataTransfer { @@ -228,8 +185,6 @@ private: void DestroyDeviceObjects(); - bool VertexCacheLookup(int &vertexCount, GEPrimitiveType &prim, VkBuffer &vbuf, uint32_t &vbOffset, VkBuffer &ibuf, uint32_t &ibOffset, bool &useElements, bool forceIndexed); - void DecodeVertsToPushPool(VulkanPushPool *push, uint32_t *bindOffset, VkBuffer *vkbuf); void DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf); @@ -254,9 +209,6 @@ private: VkSampler samplerSecondaryLinear_ = VK_NULL_HANDLE; VkSampler samplerSecondaryNearest_ = VK_NULL_HANDLE; - PrehashMap vai_; - VulkanPushBuffer *vertexCache_; - struct DescriptorSetKey { VkImageView imageView_; VkImageView secondaryImageView_; diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 79c4e2c0e4..a0a67456e0 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -650,8 +650,6 @@ void MainWindow::createMenus() gameSettingsMenu->add(new MenuAction(this, SLOT(transformAct()), QT_TR_NOOP("&Hardware transform"))) ->addEventChecked(&g_Config.bHardwareTransform); - gameSettingsMenu->add(new MenuAction(this, SLOT(vertexCacheAct()), QT_TR_NOOP("&Vertex cache"))) - ->addEventChecked(&g_Config.bVertexCache); gameSettingsMenu->addSeparator(); gameSettingsMenu->add(new MenuAction(this, SLOT(audioAct()), QT_TR_NOOP("Enable s&ound"))) ->addEventChecked(&g_Config.bEnableSound); diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index ebadf93b07..b9da7ee905 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -157,7 +157,6 @@ private slots: g_Config.bHardwareTransform = !g_Config.bHardwareTransform; System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED); } - void vertexCacheAct() { g_Config.bVertexCache = !g_Config.bVertexCache; } void frameskipAct() { g_Config.iFrameSkip = !g_Config.iFrameSkip; } void frameskipTypeAct() { g_Config.iFrameSkipType = !g_Config.iFrameSkipType; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index a4b84dc121..f5216ea7e5 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -401,15 +401,6 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) CheckBox *skipGPUReadbacks = graphicsSettings->Add(new CheckBox(&g_Config.bSkipGPUReadbacks, gr->T("Skip GPU Readbacks"))); skipGPUReadbacks->SetDisabledPtr(&g_Config.bSoftwareRendering); - CheckBox *vtxCache = graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gr->T("Vertex Cache"))); - vtxCache->OnClick.Add([=](EventParams &e) { - settingInfo_->Show(gr->T("VertexCache Tip", "Faster, but may cause temporary flicker"), e.v); - return UI::EVENT_CONTINUE; - }); - vtxCache->SetEnabledFunc([] { - return !g_Config.bSoftwareRendering && g_Config.bHardwareTransform && g_Config.iGPUBackend != (int)GPUBackend::OPENGL; - }); - CheckBox *texBackoff = graphicsSettings->Add(new CheckBox(&g_Config.bTextureBackoffCache, gr->T("Lazy texture caching", "Lazy texture caching (speedup)"))); texBackoff->SetDisabledPtr(&g_Config.bSoftwareRendering); texBackoff->OnClick.Add([=](EventParams& e) { diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 38de01c013..cc5ea9a407 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -290,7 +290,6 @@ namespace MainWindow { TranslateMenuItem(menu, ID_TEXTURESCALING_HYBRID_BICUBIC); TranslateMenuItem(menu, ID_TEXTURESCALING_DEPOSTERIZE); TranslateMenuItem(menu, ID_OPTIONS_HARDWARETRANSFORM); - TranslateMenuItem(menu, ID_OPTIONS_VERTEXCACHE); TranslateMenuItem(menu, ID_EMULATION_SOUND); TranslateMenuItem(menu, ID_EMULATION_CHEATS, g_Config.bSystemControls ? L"\tCtrl+T" : L""); TranslateMenuItem(menu, ID_EMULATION_CHAT, g_Config.bSystemControls ? L"\tCtrl+C" : L""); @@ -859,9 +858,6 @@ namespace MainWindow { SendToggleFullscreen(!g_Config.UseFullScreen()); break; - case ID_OPTIONS_VERTEXCACHE: - g_Config.bVertexCache = !g_Config.bVertexCache; - break; case ID_OPTIONS_TEXTUREFILTERING_AUTO: g_Config.iTexFiltering = TEX_FILTER_AUTO; break; case ID_OPTIONS_NEARESTFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_NEAREST; break; case ID_OPTIONS_LINEARFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_LINEAR; break; @@ -954,7 +950,6 @@ namespace MainWindow { CHECKITEM(ID_DEBUG_SHOWDEBUGSTATISTICS, (DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS); CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform); CHECKITEM(ID_DEBUG_BREAKONLOAD, !g_Config.bAutoRun); - CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); CHECKITEM(ID_OPTIONS_FRAMESKIP_AUTO, g_Config.bAutoFrameSkip); CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != FRAMESKIP_OFF); CHECKITEM(ID_OPTIONS_FRAMESKIPTYPE_COUNT, g_Config.iFrameSkipType == FRAMESKIPTYPE_COUNT); @@ -988,13 +983,6 @@ namespace MainWindow { CheckMenuItem(menu, displayrotationitems[i], MF_BYCOMMAND | ((i + 1) == g_Config.iInternalScreenRotation ? MF_CHECKED : MF_UNCHECKED)); } - // Disable Vertex Cache when HW T&L is disabled. - if (!g_Config.bHardwareTransform) { - EnableMenuItem(menu, ID_OPTIONS_VERTEXCACHE, MF_GRAYED); - } else { - EnableMenuItem(menu, ID_OPTIONS_VERTEXCACHE, MF_ENABLED); - } - static const int zoomitems[11] = { ID_OPTIONS_SCREENAUTO, ID_OPTIONS_SCREEN1X, diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 51d98e6c6e..f3c48d74cd 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -685,7 +685,6 @@ BEGIN MENUITEM "Deposterize", ID_TEXTURESCALING_DEPOSTERIZE END MENUITEM "Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM - MENUITEM "Vertex Cache", ID_OPTIONS_VERTEXCACHE MENUITEM "", 0, MFT_SEPARATOR MENUITEM "Enable Sound", ID_EMULATION_SOUND MENUITEM "", 0, MFT_SEPARATOR diff --git a/Windows/resource.h b/Windows/resource.h index 3eb5473ac1..efec1f414f 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -169,7 +169,6 @@ #define ID_OPTIONS_CONTROLS 40038 #define ID_DEBUG_BREAKONLOAD 40039 #define ID_DEBUG_DUMPNEXTFRAME 40040 -#define ID_OPTIONS_VERTEXCACHE 40041 #define ID_OPTIONS_FRAMESKIP 40044 #define IDC_MEMCHECK 40045 #define ID_FILE_MEMSTICK 40046 diff --git a/headless/Headless.cpp b/headless/Headless.cpp index c6924939e7..551176cbc3 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -472,7 +472,6 @@ int main(int argc, const char* argv[]) g_Config.bHardwareTransform = true; g_Config.iAnisotropyLevel = 0; // When testing mipmapping we really don't want this. g_Config.iMultiSampleLevel = 0; - g_Config.bVertexCache = false; g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; g_Config.bEncryptSave = true; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index bbf455cbb1..c5b4807750 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -706,15 +706,6 @@ static void check_variables(CoreParameter &coreParam) g_Config.bSoftwareSkinning = true; } - var.key = "ppsspp_vertex_cache"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (!strcmp(var.value, "disabled")) - g_Config.bVertexCache = false; - else - g_Config.bVertexCache = true; - } - var.key = "ppsspp_lazy_texture_caching"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {