From 4364569cf4efa5e0aa8ce921fbc4362397355f8d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 18:53:30 +0100 Subject: [PATCH 01/15] Move TexCacheEntry outside the TextureCacheCommon class. Nested structs are annoying. --- GPU/Common/TextureCacheCommon.cpp | 4 +- GPU/Common/TextureCacheCommon.h | 179 +++++++++++++++--------------- GPU/D3D11/TextureCacheD3D11.cpp | 2 +- GPU/Directx9/TextureCacheDX9.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 6 files changed, 96 insertions(+), 95 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 9c0bc78a32..0cb2b21a38 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -239,7 +239,7 @@ void TextureCacheCommon::AttachFramebufferValid(TexCacheEntry *entry, VirtualFra } entry->framebuffer = framebuffer; entry->invalidHint = 0; - entry->status &= ~TextureCacheCommon::TexCacheEntry::STATUS_DEPALETTIZE; + entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE; entry->maxLevel = 0; fbTexInfo_[cachekey] = fbInfo; framebuffer->last_frame_attached = gpuStats.numFlips; @@ -258,7 +258,7 @@ void TextureCacheCommon::AttachFramebufferInvalid(TexCacheEntry *entry, VirtualF } entry->framebuffer = framebuffer; entry->invalidHint = -1; - entry->status &= ~TextureCacheCommon::TexCacheEntry::STATUS_DEPALETTIZE; + entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE; entry->maxLevel = 0; fbTexInfo_[cachekey] = fbInfo; host->GPUNotifyTextureAttachment(entry->addr); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index e9987e9b18..09bf70eef4 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -76,6 +76,93 @@ struct SamplerCacheKey { } }; + +// Wow this is starting to grow big. Soon need to start looking at resizing it. +// Must stay a POD. +struct TexCacheEntry { + // After marking STATUS_UNRELIABLE, if it stays the same this many frames we'll trust it again. + const static int FRAMES_REGAIN_TRUST = 1000; + + enum Status { + STATUS_HASHING = 0x00, + STATUS_RELIABLE = 0x01, // Don't bother rehashing. + STATUS_UNRELIABLE = 0x02, // Always recheck hash. + STATUS_MASK = 0x03, + + STATUS_ALPHA_UNKNOWN = 0x04, + STATUS_ALPHA_FULL = 0x00, // Has no alpha channel, or always full alpha. + STATUS_ALPHA_SIMPLE = 0x08, // Like above, but also has 0 alpha (e.g. 5551.) + STATUS_ALPHA_MASK = 0x0c, + + STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 6 frames in between.) + STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail. + STATUS_DEPALETTIZE = 0x40, // Needs to go through a depalettize pass. + STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame. + STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.) + STATUS_FREE_CHANGE = 0x200, // Allow one change before marking "frequent". + }; + + // Status, but int so we can zero initialize. + int status; + u32 addr; + u32 hash; + VirtualFramebuffer *framebuffer; // if null, not sourced from an FBO. + u32 sizeInRAM; + int lastFrame; + int numFrames; + int numInvalidated; + u32 framesUntilNextFullHash; + u8 format; + u8 maxLevel; + u16 dim; + u16 bufw; + union { + u32 textureName; + void *texturePtr; + CachedTextureVulkan *vkTex; + }; +#ifdef _WIN32 + void *textureView; // Used by D3D11 only for the shader resource view. +#endif + int invalidHint; + u32 fullhash; + u32 cluthash; + float lodBias; + u16 maxSeenV; + + // Cache the current filter settings so we can avoid setting it again. + // (OpenGL madness where filter settings are attached to each texture. Unused in Vulkan). + u8 magFilt; + u8 minFilt; + bool sClamp; + bool tClamp; + + Status GetHashStatus() { + return Status(status & STATUS_MASK); + } + void SetHashStatus(Status newStatus) { + status = (status & ~STATUS_MASK) | newStatus; + } + Status GetAlphaStatus() { + return Status(status & STATUS_ALPHA_MASK); + } + void SetAlphaStatus(Status newStatus) { + status = (status & ~STATUS_ALPHA_MASK) | newStatus; + } + void SetAlphaStatus(Status newStatus, int level) { + // For non-level zero, only set more restrictive. + if (newStatus == STATUS_ALPHA_UNKNOWN || level == 0) { + SetAlphaStatus(newStatus); + } else if (newStatus == STATUS_ALPHA_SIMPLE && GetAlphaStatus() == STATUS_ALPHA_FULL) { + SetAlphaStatus(STATUS_ALPHA_SIMPLE); + } + } + + bool Matches(u16 dim2, u8 format2, u8 maxLevel2) const; + u64 CacheKey() const; + static u64 CacheKey(u32 addr, u8 format, u16 dim, u32 cluthash); +}; + class FramebufferManagerCommon; class TextureCacheCommon { @@ -107,92 +194,6 @@ public: return PSP_CoreParameter().compat.flags().FakeMipmapChange && gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST; } - // Wow this is starting to grow big. Soon need to start looking at resizing it. - // Must stay a POD. - struct TexCacheEntry { - // After marking STATUS_UNRELIABLE, if it stays the same this many frames we'll trust it again. - const static int FRAMES_REGAIN_TRUST = 1000; - - enum Status { - STATUS_HASHING = 0x00, - STATUS_RELIABLE = 0x01, // Don't bother rehashing. - STATUS_UNRELIABLE = 0x02, // Always recheck hash. - STATUS_MASK = 0x03, - - STATUS_ALPHA_UNKNOWN = 0x04, - STATUS_ALPHA_FULL = 0x00, // Has no alpha channel, or always full alpha. - STATUS_ALPHA_SIMPLE = 0x08, // Like above, but also has 0 alpha (e.g. 5551.) - STATUS_ALPHA_MASK = 0x0c, - - STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 6 frames in between.) - STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail. - STATUS_DEPALETTIZE = 0x40, // Needs to go through a depalettize pass. - STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame. - STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.) - STATUS_FREE_CHANGE = 0x200, // Allow one change before marking "frequent". - }; - - // Status, but int so we can zero initialize. - int status; - u32 addr; - u32 hash; - VirtualFramebuffer *framebuffer; // if null, not sourced from an FBO. - u32 sizeInRAM; - int lastFrame; - int numFrames; - int numInvalidated; - u32 framesUntilNextFullHash; - u8 format; - u8 maxLevel; - u16 dim; - u16 bufw; - union { - u32 textureName; - void *texturePtr; - CachedTextureVulkan *vkTex; - }; -#ifdef _WIN32 - void *textureView; // Used by D3D11 only for the shader resource view. -#endif - int invalidHint; - u32 fullhash; - u32 cluthash; - float lodBias; - u16 maxSeenV; - - // Cache the current filter settings so we can avoid setting it again. - // (OpenGL madness where filter settings are attached to each texture. Unused in Vulkan). - u8 magFilt; - u8 minFilt; - bool sClamp; - bool tClamp; - - Status GetHashStatus() { - return Status(status & STATUS_MASK); - } - void SetHashStatus(Status newStatus) { - status = (status & ~STATUS_MASK) | newStatus; - } - Status GetAlphaStatus() { - return Status(status & STATUS_ALPHA_MASK); - } - void SetAlphaStatus(Status newStatus) { - status = (status & ~STATUS_ALPHA_MASK) | newStatus; - } - void SetAlphaStatus(Status newStatus, int level) { - // For non-level zero, only set more restrictive. - if (newStatus == STATUS_ALPHA_UNKNOWN || level == 0) { - SetAlphaStatus(newStatus); - } else if (newStatus == STATUS_ALPHA_SIMPLE && GetAlphaStatus() == STATUS_ALPHA_FULL) { - SetAlphaStatus(STATUS_ALPHA_SIMPLE); - } - } - - bool Matches(u16 dim2, u8 format2, u8 maxLevel2) const; - u64 CacheKey() const; - static u64 CacheKey(u32 addr, u8 format, u16 dim, u32 cluthash); - }; - protected: virtual void Unbind() = 0; @@ -298,15 +299,15 @@ protected: bool nextNeedsRebuild_; }; -inline bool TextureCacheCommon::TexCacheEntry::Matches(u16 dim2, u8 format2, u8 maxLevel2) const { +inline bool TexCacheEntry::Matches(u16 dim2, u8 format2, u8 maxLevel2) const { return dim == dim2 && format == format2 && maxLevel == maxLevel2; } -inline u64 TextureCacheCommon::TexCacheEntry::CacheKey() const { +inline u64 TexCacheEntry::CacheKey() const { return CacheKey(addr, format, dim, cluthash); } -inline u64 TextureCacheCommon::TexCacheEntry::CacheKey(u32 addr, u8 format, u16 dim, u32 cluthash) { +inline u64 TexCacheEntry::CacheKey(u32 addr, u8 format, u16 dim, u32 cluthash) { u64 cachekey = ((u64)(addr & 0x3FFFFFFF) << 32) | dim; bool hasClut = (format & 4) != 0; if (hasClut) { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 8c1531d582..8641c07aaf 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -1041,7 +1041,7 @@ DXGI_FORMAT TextureCacheD3D11::GetDestFormat(GETextureFormat format, GEPaletteFo } } -TextureCacheD3D11::TexCacheEntry::Status TextureCacheD3D11::CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h) { +TexCacheEntry::Status TextureCacheD3D11::CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { case DXGI_FORMAT_B4G4R4A4_UNORM: diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index db6b5924de..5e1efd93eb 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -1058,7 +1058,7 @@ D3DFORMAT TextureCacheDX9::GetDestFormat(GETextureFormat format, GEPaletteFormat } } -TextureCacheDX9::TexCacheEntry::Status TextureCacheDX9::CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h) { +TexCacheEntry::Status TextureCacheDX9::CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { case D3DFMT_A4R4G4B4: diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 58a4a1ea43..56bb45cf50 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -1173,7 +1173,7 @@ void *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteF return finalBuf; } -TextureCacheGLES::TexCacheEntry::Status TextureCacheGLES::CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h) { +TexCacheEntry::Status TextureCacheGLES::CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { case GL_UNSIGNED_SHORT_4_4_4_4: diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 4eb9d162c0..30e6554b43 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -1149,7 +1149,7 @@ VkFormat TextureCacheVulkan::GetDestFormat(GETextureFormat format, GEPaletteForm } } -TextureCacheVulkan::TexCacheEntry::Status TextureCacheVulkan::CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h) { +TexCacheEntry::Status TextureCacheVulkan::CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h) { CheckAlphaResult res; switch (dstFmt) { case VULKAN_4444_FORMAT: From 91611832dcbaa36b49d2f967c81134c9af2b0dd4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 22:02:30 +0100 Subject: [PATCH 02/15] Vulkan crashfix --- GPU/Vulkan/GPU_Vulkan.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index f68623dcc3..a3d71a730d 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -1,3 +1,4 @@ + // Copyright (c) 2015- PPSSPP Project. // This program is free software: you can redistribute it and/or modify @@ -411,6 +412,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) framebufferManagerVulkan_->Init(); framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_); framebufferManagerVulkan_->SetDrawEngine(&drawEngine_); + framebufferManagerVulkan_->SetShaderManager(shaderManagerVulkan_); textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_); textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_); textureCacheVulkan_->SetShaderManager(shaderManagerVulkan_); From dbafc6ef955ea42706a3f20da1ff45508b8a8722 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 22:31:07 +0100 Subject: [PATCH 03/15] Centralize Texcache::Clear --- GPU/Common/TextureCacheCommon.cpp | 20 ++++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 2 ++ GPU/D3D11/TextureCacheD3D11.cpp | 30 +++++++++--------------------- GPU/D3D11/TextureCacheD3D11.h | 14 +------------- GPU/Directx9/TextureCacheDX9.cpp | 28 ++++++---------------------- GPU/Directx9/TextureCacheDX9.h | 10 +--------- GPU/GLES/TextureCacheGLES.cpp | 25 ++++++------------------- GPU/GLES/TextureCacheGLES.h | 1 + GPU/Vulkan/TextureCacheVulkan.cpp | 22 +++------------------- GPU/Vulkan/TextureCacheVulkan.h | 2 +- 10 files changed, 50 insertions(+), 104 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 0cb2b21a38..6ab7cfb06b 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -965,6 +965,26 @@ bool TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const return true; } +void TextureCacheCommon::Clear(bool delete_them) { + ForgetLastTexture(); + if (delete_them) { + for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { + ReleaseTexture(&iter->second); + } + for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { + ReleaseTexture(&iter->second); + } + } + if (cache.size() + secondCache.size()) { + INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); + cache.clear(); + secondCache.clear(); + cacheSizeEstimate_ = 0; + secondCacheSizeEstimate_ = 0; + } + fbTexInfo_.clear(); + videos_.clear(); +} bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 09bf70eef4..9eb8a9e360 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -178,6 +178,7 @@ public: void InvalidateAll(GPUInvalidationType type); void ClearNextFrame(); virtual void ForgetLastTexture() = 0; + virtual void Clear(bool delete_them); // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); @@ -196,6 +197,7 @@ public: protected: virtual void Unbind() = 0; + virtual void ReleaseTexture(TexCacheEntry *entry) = 0; bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 8641c07aaf..ff7ad8fd9c 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -134,29 +134,17 @@ void TextureCacheD3D11::SetFramebufferManager(FramebufferManagerD3D11 *fbManager framebufferManager_ = fbManager; } -void TextureCacheD3D11::Clear(bool delete_them) { - // ID3D11ShaderResourceView *srv = nullptr; - // context_->PSSetShaderResources(0, 1, &srv); - lastBoundTexture = INVALID_TEX; - if (delete_them) { - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.texturePtr); - ReleaseTexture(&iter->second); - } - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.texturePtr); - ReleaseTexture(&iter->second); - } +void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry) { + ID3D11Texture2D *texture = (ID3D11Texture2D *)entry->texturePtr; + ID3D11ShaderResourceView *view = (ID3D11ShaderResourceView *)entry->textureView; + if (texture) { + texture->Release(); + entry->texturePtr = nullptr; } - if (cache.size() + secondCache.size()) { - INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); - cache.clear(); - secondCache.clear(); - cacheSizeEstimate_ = 0; - secondCacheSizeEstimate_ = 0; + if (view) { + view->Release(); + entry->textureView = nullptr; } - fbTexInfo_.clear(); - videos_.clear(); } void TextureCacheD3D11::DeleteTexture(TexCache::iterator it) { diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 4c4f2e2d66..2fe76de9b4 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -48,7 +48,6 @@ public: void SetTexture(bool force = false); - void Clear(bool delete_them); void StartFrame(); void SetFramebufferManager(FramebufferManagerD3D11 *fbManager); @@ -70,6 +69,7 @@ public: protected: void Unbind() override; + void ReleaseTexture(TexCacheEntry *entry) override; private: void Decimate(); // Run this once per frame to get rid of old textures. @@ -95,18 +95,6 @@ private: ID3D11ShaderResourceView *DxView(TexCacheEntry *entry) { return (ID3D11ShaderResourceView *)entry->textureView; } - void ReleaseTexture(TexCacheEntry *entry) { - ID3D11Texture2D *texture = (ID3D11Texture2D *)entry->texturePtr; - ID3D11ShaderResourceView *view = (ID3D11ShaderResourceView *)entry->textureView; - if (texture) { - texture->Release(); - entry->texturePtr = nullptr; - } - if (view) { - view->Release(); - entry->textureView = nullptr; - } - } TextureScalerD3D11 scaler; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 5e1efd93eb..f18f369b33 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -98,28 +98,13 @@ void TextureCacheDX9::SetFramebufferManager(FramebufferManagerDX9 *fbManager) { framebufferManager_ = fbManager; } -void TextureCacheDX9::Clear(bool delete_them) { - pD3Ddevice->SetTexture(0, NULL); - lastBoundTexture = INVALID_TEX; - if (delete_them) { - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.texturePtr); - ReleaseTexture(&iter->second); - } - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.texturePtr); - ReleaseTexture(&iter->second); - } +void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry) { + DEBUG_LOG(G3D, "Deleting texture %p", entry->texturePtr); + LPDIRECT3DTEXTURE9 &texture = DxTex(entry); + if (texture) { + texture->Release(); + texture = nullptr; } - if (cache.size() + secondCache.size()) { - INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); - cache.clear(); - secondCache.clear(); - cacheSizeEstimate_ = 0; - secondCacheSizeEstimate_ = 0; - } - fbTexInfo_.clear(); - videos_.clear(); } void TextureCacheDX9::DeleteTexture(TexCache::iterator it) { @@ -128,7 +113,6 @@ void TextureCacheDX9::DeleteTexture(TexCache::iterator it) { if (fbInfo != fbTexInfo_.end()) { fbTexInfo_.erase(fbInfo); } - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); cache.erase(it); } diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 2c5a8a8401..d8ede25c4f 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -41,8 +41,6 @@ public: ~TextureCacheDX9(); void SetTexture(bool force = false); - - void Clear(bool delete_them); void StartFrame(); void SetFramebufferManager(FramebufferManagerDX9 *fbManager); @@ -64,6 +62,7 @@ public: protected: void Unbind() override; + void ReleaseTexture(TexCacheEntry *entry) override; private: void Decimate(); // Run this once per frame to get rid of old textures. @@ -83,13 +82,6 @@ private: LPDIRECT3DTEXTURE9 &DxTex(TexCacheEntry *entry) { return *(LPDIRECT3DTEXTURE9 *)&entry->texturePtr; } - void ReleaseTexture(TexCacheEntry *entry) { - LPDIRECT3DTEXTURE9 &texture = DxTex(entry); - if (texture) { - texture->Release(); - texture = nullptr; - } - } TextureScalerDX9 scaler; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 56bb45cf50..7dc7450b08 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -86,32 +86,19 @@ void TextureCacheGLES::SetFramebufferManager(FramebufferManagerGLES *fbManager) framebufferManager_ = fbManager; } +void TextureCacheGLES::ReleaseTexture(TexCacheEntry *entry) { + DEBUG_LOG(G3D, "Deleting texture %i", entry->textureName); + glDeleteTextures(1, &entry->textureName); +} + void TextureCacheGLES::Clear(bool delete_them) { - glBindTexture(GL_TEXTURE_2D, 0); - lastBoundTexture = INVALID_TEX; + TextureCacheCommon::Clear(delete_them); if (delete_them) { - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %i", iter->second.textureName); - glDeleteTextures(1, &iter->second.textureName); - } - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %i", iter->second.textureName); - glDeleteTextures(1, &iter->second.textureName); - } if (!nameCache_.empty()) { glDeleteTextures((GLsizei)nameCache_.size(), &nameCache_[0]); nameCache_.clear(); } } - if (cache.size() + secondCache.size()) { - INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); - cache.clear(); - secondCache.clear(); - cacheSizeEstimate_ = 0; - secondCacheSizeEstimate_ = 0; - } - fbTexInfo_.clear(); - videos_.clear(); } void TextureCacheGLES::DeleteTexture(TexCache::iterator it) { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index e3c031b600..7f54503d5c 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -78,6 +78,7 @@ public: protected: void Unbind() override; + void ReleaseTexture(TexCacheEntry *entry) override; private: void Decimate(); // Run this once per frame to get rid of old textures. diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 30e6554b43..fa6b2e1b95 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -192,25 +192,9 @@ void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan) { samplerCache_.DeviceRestore(vulkan); } -void TextureCacheVulkan::Clear(bool delete_them) { - lastBoundTexture = nullptr; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex); - delete iter->second.vkTex; - } - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { - DEBUG_LOG(G3D, "Deleting texture %p", iter->second.vkTex); - delete iter->second.vkTex; - } - if (cache.size() + secondCache.size()) { - INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); - cache.clear(); - secondCache.clear(); - cacheSizeEstimate_ = 0; - secondCacheSizeEstimate_ = 0; - } - fbTexInfo_.clear(); - videos_.clear(); +void TextureCacheVulkan::ReleaseTexture(TexCacheEntry *entry) { + DEBUG_LOG(G3D, "Deleting texture %p", entry->vkTex); + delete entry->vkTex; } void TextureCacheVulkan::DeleteTexture(TexCache::iterator it) { diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index f0318a3f26..986b6c34ba 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -68,7 +68,6 @@ public: ~TextureCacheVulkan(); void SetTexture(); - void Clear(bool delete_them); void StartFrame(); void EndFrame(); @@ -95,6 +94,7 @@ public: protected: void Unbind() override; + void ReleaseTexture(TexCacheEntry *entry) override; private: void Decimate(); // Run this once per frame to get rid of old textures. From 665ffe34ab214dd6ee7ae0edbf5dbb38af9f562b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 22:50:04 +0100 Subject: [PATCH 04/15] Centralize DeleteTexture --- GPU/Common/TextureCacheCommon.cpp | 10 ++++++++++ GPU/Common/TextureCacheCommon.h | 8 +++++--- GPU/D3D11/TextureCacheD3D11.cpp | 17 +---------------- GPU/D3D11/TextureCacheD3D11.h | 4 ---- GPU/Directx9/TextureCacheDX9.cpp | 6 +----- GPU/Directx9/TextureCacheDX9.h | 3 --- GPU/GLES/TextureCacheGLES.cpp | 17 +---------------- GPU/GLES/TextureCacheGLES.h | 4 ---- GPU/Vulkan/TextureCacheVulkan.cpp | 6 +----- GPU/Vulkan/TextureCacheVulkan.h | 3 --- 10 files changed, 19 insertions(+), 59 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 6ab7cfb06b..0f2491156f 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -986,6 +986,16 @@ void TextureCacheCommon::Clear(bool delete_them) { videos_.clear(); } +void TextureCacheCommon::DeleteTexture(TexCache::iterator it) { + ReleaseTexture(&it->second); + auto fbInfo = fbTexInfo_.find(it->first); + if (fbInfo != fbTexInfo_.end()) { + fbTexInfo_.erase(fbInfo); + } + cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); + cache.erase(it); +} + bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 9eb8a9e360..60242b251f 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -164,6 +164,8 @@ struct TexCacheEntry { }; class FramebufferManagerCommon; +// Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC. +typedef std::map TexCache; class TextureCacheCommon { public: @@ -198,12 +200,10 @@ public: protected: virtual void Unbind() = 0; virtual void ReleaseTexture(TexCacheEntry *entry) = 0; + void DeleteTexture(TexCache::iterator it); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); - // Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC. - typedef std::map TexCache; - // Separate to keep main texture cache size down. struct AttachedFramebufferInfo { u32 xOffset; @@ -279,6 +279,8 @@ protected: TexCacheEntry *nextTexture_; + u32 clutHash_ = 0; + // Raw is where we keep the original bytes. Converted is where we swap colors if necessary. u32 *clutBufRaw_; u32 *clutBufConverted_; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index ff7ad8fd9c..d2fee8f3ff 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -147,17 +147,6 @@ void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry) { } } -void TextureCacheD3D11::DeleteTexture(TexCache::iterator it) { - ReleaseTexture(&it->second); - auto fbInfo = fbTexInfo_.find(it->first); - if (fbInfo != fbTexInfo_.end()) { - fbTexInfo_.erase(fbInfo); - } - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache.erase(it); -} - void TextureCacheD3D11::ForgetLastTexture() { lastBoundTexture = INVALID_TEX; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); @@ -323,10 +312,6 @@ void TextureCacheD3D11::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBa clutLastFormat_ = gstate.clutformat; } -inline u32 TextureCacheD3D11::GetCurrentClutHash() { - return clutHash_; -} - void TextureCacheD3D11::Unbind() { ID3D11ShaderResourceView *nullView = nullptr; context_->PSSetShaderResources(0, 1, &nullView); @@ -607,7 +592,7 @@ void TextureCacheD3D11::SetTexture(bool force) { // We update here because the clut format can be specified after the load. UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); } - cluthash = GetCurrentClutHash() ^ gstate.clutformat; + cluthash = clutHash_ ^ gstate.clutformat; } else { cluthash = 0; } diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 2fe76de9b4..df63052820 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -73,12 +73,10 @@ protected: private: void Decimate(); // Run this once per frame to get rid of old textures. - void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); - u32 GetCurrentClutHash(); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); @@ -100,8 +98,6 @@ private: SamplerCacheD3D11 samplerCache_; - u32 clutHash_; - ID3D11ShaderResourceView *lastBoundTexture; int decimationCounter_; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index f18f369b33..d1deefb5d6 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -332,10 +332,6 @@ void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase clutLastFormat_ = gstate.clutformat; } -inline u32 TextureCacheDX9::GetCurrentClutHash() { - return clutHash_; -} - void TextureCacheDX9::Unbind() { pD3Ddevice->SetTexture(0, NULL); } @@ -618,7 +614,7 @@ void TextureCacheDX9::SetTexture(bool force) { // We update here because the clut format can be specified after the load. UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); } - cluthash = GetCurrentClutHash() ^ gstate.clutformat; + cluthash = clutHash_ ^ gstate.clutformat; } else { cluthash = 0; } diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index d8ede25c4f..4edae8f3d5 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -71,7 +71,6 @@ private: void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); - u32 GetCurrentClutHash(); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); @@ -85,8 +84,6 @@ private: TextureScalerDX9 scaler; - u32 clutHash_; - LPDIRECT3DVERTEXDECLARATION9 pFramebufferVertexDecl; LPDIRECT3DTEXTURE9 lastBoundTexture; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 7dc7450b08..97cc9282a7 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -101,17 +101,6 @@ void TextureCacheGLES::Clear(bool delete_them) { } } -void TextureCacheGLES::DeleteTexture(TexCache::iterator it) { - glDeleteTextures(1, &it->second.textureName); - auto fbInfo = fbTexInfo_.find(it->first); - if (fbInfo != fbTexInfo_.end()) { - fbTexInfo_.erase(fbInfo); - } - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache.erase(it); -} - // Removes old textures. void TextureCacheGLES::Decimate() { if (--decimationCounter_ <= 0) { @@ -354,10 +343,6 @@ void TextureCacheGLES::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBas clutLastFormat_ = gstate.clutformat; } -inline u32 TextureCacheGLES::GetCurrentClutHash() { - return clutHash_; -} - // #define DEBUG_TEXTURES #ifdef DEBUG_TEXTURES @@ -703,7 +688,7 @@ void TextureCacheGLES::SetTexture(bool force) { // We update here because the clut format can be specified after the load. UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); } - cluthash = GetCurrentClutHash() ^ gstate.clutformat; + cluthash = clutHash_ ^ gstate.clutformat; } else { cluthash = 0; } diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 7f54503d5c..06111ca3b8 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -82,13 +82,11 @@ protected: private: void Decimate(); // Run this once per frame to get rid of old textures. - void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, bool force); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt); GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; void *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); TexCacheEntry::Status CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h); - u32 GetCurrentClutHash(); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); @@ -99,8 +97,6 @@ private: TextureScalerGLES scaler; - u32 clutHash_; - u32 lastBoundTexture; float maxAnisotropyLevel; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index fa6b2e1b95..d992c479a9 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -397,10 +397,6 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB clutLastFormat_ = gstate.clutformat; } -inline u32 TextureCacheVulkan::GetCurrentClutHash() { - return clutHash_; -} - void TextureCacheVulkan::Unbind() { } @@ -639,7 +635,7 @@ void TextureCacheVulkan::SetTexture() { // We update here because the clut format can be specified after the load. UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); } - cluthash = GetCurrentClutHash() ^ gstate.clutformat; + cluthash = clutHash_ ^ gstate.clutformat; } else { cluthash = 0; } diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 986b6c34ba..a85034618e 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -103,7 +103,6 @@ private: void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt); VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h); - u32 GetCurrentClutHash(); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); void ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEntry *entry, VirtualFramebuffer *framebuffer, VkImageView &image, VkSampler &sampler); void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); @@ -119,8 +118,6 @@ private: TextureScalerVulkan scaler; - u32 clutHash_; - CachedTextureVulkan *lastBoundTexture; int decimationCounter_; From f839f1944e5a64caac97be7fea5c3fcfebb6d3fe Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 23:07:00 +0100 Subject: [PATCH 05/15] Work towards unifying ApplyTexture --- GPU/Common/TextureCacheCommon.h | 2 ++ GPU/D3D11/TextureCacheD3D11.cpp | 14 +++++++++----- GPU/D3D11/TextureCacheD3D11.h | 1 + GPU/Directx9/TextureCacheDX9.cpp | 14 +++++++++----- GPU/Directx9/TextureCacheDX9.h | 1 + GPU/GLES/TextureCacheGLES.cpp | 12 ++++++++---- GPU/GLES/TextureCacheGLES.h | 1 + GPU/Vulkan/DrawEngineVulkan.cpp | 4 ++-- GPU/Vulkan/TextureCacheVulkan.cpp | 14 +++++++++----- GPU/Vulkan/TextureCacheVulkan.h | 9 +++++---- 10 files changed, 47 insertions(+), 25 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 60242b251f..2fe2e9cfda 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -179,6 +179,7 @@ public: void Invalidate(u32 addr, int size, GPUInvalidationType type); void InvalidateAll(GPUInvalidationType type); void ClearNextFrame(); + virtual void ForgetLastTexture() = 0; virtual void Clear(bool delete_them); @@ -198,6 +199,7 @@ public: } protected: + virtual void BindTexture(TexCacheEntry *entry) = 0; virtual void Unbind() = 0; virtual void ReleaseTexture(TexCacheEntry *entry) = 0; void DeleteTexture(TexCache::iterator it); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d2fee8f3ff..c669b42d7e 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -312,6 +312,14 @@ void TextureCacheD3D11::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBa clutLastFormat_ = gstate.clutformat; } +void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) { + ID3D11ShaderResourceView *textureView = DxView(entry); + if (textureView != lastBoundTexture) { + context_->PSSetShaderResources(0, 1, &textureView); + lastBoundTexture = textureView; + } +} + void TextureCacheD3D11::Unbind() { ID3D11ShaderResourceView *nullView = nullptr; context_->PSSetShaderResources(0, 1, &nullView); @@ -363,11 +371,7 @@ void TextureCacheD3D11::ApplyTexture() { if (entry->framebuffer) { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { - ID3D11ShaderResourceView *textureView = DxView(entry); - if (textureView != lastBoundTexture) { - context_->PSSetShaderResources(0, 1, &textureView); - lastBoundTexture = textureView; - } + BindTexture(entry); SamplerCacheKey key; UpdateSamplingParams(*entry, key); ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, key); diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index df63052820..824fafe657 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -68,6 +68,7 @@ public: void ApplyTexture(); protected: + void BindTexture(TexCacheEntry *entry) override; void Unbind() override; void ReleaseTexture(TexCacheEntry *entry) override; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index d1deefb5d6..572425f8f7 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -332,6 +332,14 @@ void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase clutLastFormat_ = gstate.clutformat; } +void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { + LPDIRECT3DTEXTURE9 texture = DxTex(entry); + if (texture != lastBoundTexture) { + pD3Ddevice->SetTexture(0, texture); + lastBoundTexture = texture; + } +} + void TextureCacheDX9::Unbind() { pD3Ddevice->SetTexture(0, NULL); } @@ -382,11 +390,7 @@ void TextureCacheDX9::ApplyTexture() { if (entry->framebuffer) { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { - LPDIRECT3DTEXTURE9 texture = DxTex(entry); - if (texture != lastBoundTexture) { - pD3Ddevice->SetTexture(0, texture); - lastBoundTexture = texture; - } + BindTexture(entry); UpdateSamplingParams(*entry, false); gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 4edae8f3d5..dc3ef86183 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -61,6 +61,7 @@ public: void ApplyTexture(); protected: + void BindTexture(TexCacheEntry *entry) override; void Unbind() override; void ReleaseTexture(TexCacheEntry *entry) override; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 97cc9282a7..c79401742c 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -385,6 +385,13 @@ bool SetDebugTexture() { } #endif +void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { + if (entry->textureName != lastBoundTexture) { + glBindTexture(GL_TEXTURE_2D, entry->textureName); + lastBoundTexture = entry->textureName; + } +} + void TextureCacheGLES::Unbind() { glBindTexture(GL_TEXTURE_2D, 0); } @@ -434,10 +441,7 @@ void TextureCacheGLES::ApplyTexture() { if (entry->framebuffer) { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { - if (entry->textureName != lastBoundTexture) { - glBindTexture(GL_TEXTURE_2D, entry->textureName); - lastBoundTexture = entry->textureName; - } + BindTexture(entry); UpdateSamplingParams(*entry, false); gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 06111ca3b8..4993322f98 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -77,6 +77,7 @@ public: void ApplyTexture(); protected: + void BindTexture(TexCacheEntry *entry) override; void Unbind() override; void ReleaseTexture(TexCacheEntry *entry) override; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index b6f445a95c..4db14a367c 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -668,7 +668,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { } if (textureNeedsApply) { - textureCache_->ApplyTexture(frame->pushUBO, imageView, sampler); + textureCache_->ApplyTexture(imageView, sampler); if (imageView == VK_NULL_HANDLE) imageView = nullTexture_->GetImageView(); if (sampler == VK_NULL_HANDLE) @@ -768,7 +768,7 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { // to use a "pre-clear" render pass, for high efficiency on tilers. if (result.action == SW_DRAW_PRIMITIVES) { if (textureNeedsApply) { - textureCache_->ApplyTexture(frame->pushUBO, imageView, sampler); + textureCache_->ApplyTexture(imageView, sampler); if (imageView == VK_NULL_HANDLE) imageView = nullTexture_->GetImageView(); if (sampler == VK_NULL_HANDLE) diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index d992c479a9..4c6e0138fe 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -397,10 +397,14 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB clutLastFormat_ = gstate.clutformat; } +void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) { + +} + void TextureCacheVulkan::Unbind() { } -void TextureCacheVulkan::ApplyTexture(VulkanPushBuffer *uploadBuffer, VkImageView &imageView, VkSampler &sampler) { +void TextureCacheVulkan::ApplyTexture(VkImageView &imageView, VkSampler &sampler) { TexCacheEntry *entry = nextTexture_; if (entry == nullptr) { imageView = VK_NULL_HANDLE; @@ -440,7 +444,7 @@ void TextureCacheVulkan::ApplyTexture(VulkanPushBuffer *uploadBuffer, VkImageVie // Okay, now actually rebuild the texture if needed. if (nextNeedsRebuild_) { - BuildTexture(entry, uploadBuffer); + BuildTexture(entry); } entry->lastFrame = gpuStats.numFlips; @@ -538,7 +542,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEn uv[3] = UV(uvleft, uvtop); } - shaderManager_->DirtyLastShader(); + shaderManagerVulkan_->DirtyLastShader(); //depalFBO->EndPass(cmd); //depalFBO->TransitionToTexture(cmd); @@ -901,7 +905,7 @@ bool TextureCacheVulkan::HandleTextureChange(TexCacheEntry *const entry, const c return false; } -void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, VulkanPushBuffer *uploadBuffer) { +void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; // For the estimate, we assume cluts always point to 8888 for simplicity. @@ -1079,7 +1083,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, VulkanPushBuff int size = stride * mipHeight; uint32_t bufferOffset; VkBuffer texBuf; - void *data = uploadBuffer->Push(size, &bufferOffset, &texBuf); + void *data = drawEngine_->GetPushBufferForTextureData()->Push(size, &bufferOffset, &texBuf); if (replaced.Valid()) { replaced.Load(i, data, stride); } else { diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index a85034618e..c7163516f2 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -79,7 +79,7 @@ public: depalShaderCache_ = dpCache; } void SetShaderManager(ShaderManagerVulkan *sm) { - shaderManager_ = sm; + shaderManagerVulkan_ = sm; } void SetDrawEngine(DrawEngineVulkan *td) { drawEngine_ = td; @@ -90,9 +90,10 @@ public: gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } - void ApplyTexture(VulkanPushBuffer *uploadBuffer, VkImageView &imageView, VkSampler &sampler); + void ApplyTexture(VkImageView &imageView, VkSampler &sampler); protected: + void BindTexture(TexCacheEntry *entry) override; void Unbind() override; void ReleaseTexture(TexCacheEntry *entry) override; @@ -109,7 +110,7 @@ private: bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); - void BuildTexture(TexCacheEntry *const entry, VulkanPushBuffer *uploadBuffer); + void BuildTexture(TexCacheEntry *const entry); VulkanContext *vulkan_; VulkanDeviceAllocator *allocator_; @@ -126,7 +127,7 @@ private: FramebufferManagerVulkan *framebufferManagerVulkan_; DepalShaderCacheVulkan *depalShaderCache_; - ShaderManagerVulkan *shaderManager_; + ShaderManagerVulkan *shaderManagerVulkan_; DrawEngineVulkan *drawEngine_; }; From 7890b61cc54394c45744c969e7b1f7cde734a42a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 23:19:55 +0100 Subject: [PATCH 06/15] More work towards unifying ApplyTexture --- GPU/D3D11/TextureCacheD3D11.cpp | 9 ++++---- GPU/Directx9/TextureCacheDX9.cpp | 3 +-- GPU/GLES/TextureCacheGLES.cpp | 3 +-- GPU/Vulkan/DrawEngineVulkan.cpp | 6 ++++-- GPU/Vulkan/DrawEngineVulkan.h | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 35 ++++++++++++++++--------------- GPU/Vulkan/TextureCacheVulkan.h | 12 +++++++++-- 7 files changed, 40 insertions(+), 30 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index c669b42d7e..1b280be4cf 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -318,6 +318,10 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) { context_->PSSetShaderResources(0, 1, &textureView); lastBoundTexture = textureView; } + SamplerCacheKey key; + UpdateSamplingParams(*entry, key); + ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, key); + context_->PSSetSamplers(0, 1, &state); } void TextureCacheD3D11::Unbind() { @@ -328,6 +332,7 @@ void TextureCacheD3D11::Unbind() { void TextureCacheD3D11::ApplyTexture() { TexCacheEntry *entry = nextTexture_; if (entry == nullptr) { + // Unbind? return; } nextTexture_ = nullptr; @@ -372,10 +377,6 @@ void TextureCacheD3D11::ApplyTexture() { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { BindTexture(entry); - SamplerCacheKey key; - UpdateSamplingParams(*entry, key); - ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, key); - context_->PSSetSamplers(0, 1, &state); gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 572425f8f7..e145ae5708 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -338,6 +338,7 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { pD3Ddevice->SetTexture(0, texture); lastBoundTexture = texture; } + UpdateSamplingParams(*entry, false); } void TextureCacheDX9::Unbind() { @@ -391,8 +392,6 @@ void TextureCacheDX9::ApplyTexture() { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { BindTexture(entry); - UpdateSamplingParams(*entry, false); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index c79401742c..6c3684b9a6 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -390,6 +390,7 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { glBindTexture(GL_TEXTURE_2D, entry->textureName); lastBoundTexture = entry->textureName; } + UpdateSamplingParams(*entry, false); } void TextureCacheGLES::Unbind() { @@ -442,8 +443,6 @@ void TextureCacheGLES::ApplyTexture() { ApplyTextureFramebuffer(entry, entry->framebuffer); } else { BindTexture(entry); - UpdateSamplingParams(*entry, false); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 4db14a367c..868bacb592 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -668,7 +668,8 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { } if (textureNeedsApply) { - textureCache_->ApplyTexture(imageView, sampler); + textureCache_->ApplyTexture(); + textureCache_->GetVulkanHandles(imageView, sampler); if (imageView == VK_NULL_HANDLE) imageView = nullTexture_->GetImageView(); if (sampler == VK_NULL_HANDLE) @@ -768,7 +769,8 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) { // to use a "pre-clear" render pass, for high efficiency on tilers. if (result.action == SW_DRAW_PRIMITIVES) { if (textureNeedsApply) { - textureCache_->ApplyTexture(imageView, sampler); + textureCache_->ApplyTexture(); + textureCache_->GetVulkanHandles(imageView, sampler); if (imageView == VK_NULL_HANDLE) imageView = nullTexture_->GetImageView(); if (sampler == VK_NULL_HANDLE) diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index f94d61f93f..cd77564093 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -123,7 +123,7 @@ public: void DirtyAllUBOs(); VulkanPushBuffer *GetPushBufferForTextureData() { - return frame_[curFrame_].pushUBO; + return frame_[curFrame_ & 1].pushUBO; } const DrawEngineVulkanStats &GetStats() const { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 4c6e0138fe..0de9df3e0c 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -398,17 +398,27 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB } void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) { + if (!entry || !entry->vkTex) { + imageView_ = VK_NULL_HANDLE; + sampler_ = VK_NULL_HANDLE; + return; + } + imageView_ = entry->vkTex->texture_->GetImageView(); + SamplerCacheKey key; + UpdateSamplingParams(*entry, key); + sampler_ = samplerCache_.GetOrCreateSampler(key); } void TextureCacheVulkan::Unbind() { + imageView_ = VK_NULL_HANDLE; + sampler_ = VK_NULL_HANDLE; } -void TextureCacheVulkan::ApplyTexture(VkImageView &imageView, VkSampler &sampler) { +void TextureCacheVulkan::ApplyTexture() { TexCacheEntry *entry = nextTexture_; if (entry == nullptr) { - imageView = VK_NULL_HANDLE; - sampler = VK_NULL_HANDLE; + // Unbind(); return; } nextTexture_ = nullptr; @@ -448,27 +458,18 @@ void TextureCacheVulkan::ApplyTexture(VkImageView &imageView, VkSampler &sampler } entry->lastFrame = gpuStats.numFlips; - VkCommandBuffer cmd = nullptr; if (entry->framebuffer) { - ApplyTextureFramebuffer(cmd, entry, entry->framebuffer, imageView, sampler); - } else if (entry->vkTex) { - imageView = entry->vkTex->texture_->GetImageView(); - - SamplerCacheKey key; - UpdateSamplingParams(*entry, key); - sampler = samplerCache_.GetOrCreateSampler(key); - + ApplyTextureFramebuffer(entry, entry->framebuffer); + } else { + BindTexture(entry); gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; lastBoundTexture = entry->vkTex; - } else { - imageView = VK_NULL_HANDLE; - sampler = VK_NULL_HANDLE; } } -void TextureCacheVulkan::ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEntry *entry, VirtualFramebuffer *framebuffer, VkImageView &imageView, VkSampler &sampler) { +void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) { DepalShaderVulkan *depal = nullptr; const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); if ((entry->status & TexCacheEntry::STATUS_DEPALETTIZE) && !g_Config.bDisableSlowFramebufEffects) { @@ -574,7 +575,7 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEn SamplerCacheKey key; UpdateSamplingParams(*entry, key); key.mipEnable = false; - sampler = samplerCache_.GetOrCreateSampler(key); + sampler_ = samplerCache_.GetOrCreateSampler(key); lastBoundTexture = nullptr; } diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index c7163516f2..4014a04498 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -90,7 +90,11 @@ public: gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } - void ApplyTexture(VkImageView &imageView, VkSampler &sampler); + void ApplyTexture(); + void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { + imageView = imageView_; + sampler = sampler_; + } protected: void BindTexture(TexCacheEntry *entry) override; @@ -105,7 +109,7 @@ private: VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); - void ApplyTextureFramebuffer(VkCommandBuffer cmd, TexCacheEntry *entry, VirtualFramebuffer *framebuffer, VkImageView &image, VkSampler &sampler); + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); @@ -129,6 +133,10 @@ private: DepalShaderCacheVulkan *depalShaderCache_; ShaderManagerVulkan *shaderManagerVulkan_; DrawEngineVulkan *drawEngine_; + + // Bound state to emulate an API similar to the others + VkImageView imageView_ = VK_NULL_HANDLE; + VkSampler sampler_ = VK_NULL_HANDLE; }; VkFormat getClutDestFormatVulkan(GEPaletteFormat format); From d9c20fbaff9650927e05c41b8360f90aac39760f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 23:25:09 +0100 Subject: [PATCH 07/15] Unify ApplyTexture --- GPU/Common/TextureCacheCommon.cpp | 52 ++++++++++++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 5 +++ GPU/D3D11/TextureCacheD3D11.cpp | 53 ----------------------------- GPU/D3D11/TextureCacheD3D11.h | 9 +++-- GPU/Directx9/TextureCacheDX9.cpp | 52 ---------------------------- GPU/Directx9/TextureCacheDX9.h | 8 ++--- GPU/GLES/TextureCacheGLES.cpp | 51 ---------------------------- GPU/GLES/TextureCacheGLES.h | 8 ++--- GPU/Vulkan/TextureCacheVulkan.cpp | 56 +------------------------------ GPU/Vulkan/TextureCacheVulkan.h | 7 ++-- 10 files changed, 71 insertions(+), 230 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 0f2491156f..9c00e8a44e 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -965,6 +965,58 @@ bool TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const return true; } + +void TextureCacheCommon::ApplyTexture() { + TexCacheEntry *entry = nextTexture_; + if (entry == nullptr) { + return; + } + nextTexture_ = nullptr; + + UpdateMaxSeenV(entry, gstate.isModeThrough()); + + bool replaceImages = false; + if (nextNeedsRebuild_) { + if (nextNeedsRehash_) { + // Update the hash on the texture. + int w = gstate.getTextureWidth(0); + int h = gstate.getTextureHeight(0); + entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + } + if (nextNeedsChange_) { + // This texture existed previously, let's handle the change. + replaceImages = HandleTextureChange(entry, nextChangeReason_, false, true); + } + // We actually build afterward (shared with rehash rebuild.) + } else if (nextNeedsRehash_) { + // Okay, this matched and didn't change - but let's check the hash. Maybe it will change. + bool doDelete = true; + if (!CheckFullHash(entry, doDelete)) { + replaceImages = HandleTextureChange(entry, "hash fail", true, doDelete); + nextNeedsRebuild_ = true; + } else if (nextTexture_ != nullptr) { + // Secondary cache picked a different texture, use it. + entry = nextTexture_; + nextTexture_ = nullptr; + UpdateMaxSeenV(entry, gstate.isModeThrough()); + } + } + + // Okay, now actually rebuild the texture if needed. + if (nextNeedsRebuild_) { + BuildTexture(entry, replaceImages); + } + + entry->lastFrame = gpuStats.numFlips; + if (entry->framebuffer) { + ApplyTextureFramebuffer(entry, entry->framebuffer); + } else { + BindTexture(entry); + gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; + gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; + } +} + void TextureCacheCommon::Clear(bool delete_them) { ForgetLastTexture(); if (delete_them) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 2fe2e9cfda..ef26104f5e 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -175,6 +175,7 @@ public: void LoadClut(u32 clutAddr, u32 loadBytes); bool GetCurrentClutBuffer(GPUDebugBuffer &buffer); + void ApplyTexture(); bool SetOffsetTexture(u32 offset); void Invalidate(u32 addr, int size, GPUInvalidationType type); void InvalidateAll(GPUInvalidationType type); @@ -204,6 +205,10 @@ protected: virtual void ReleaseTexture(TexCacheEntry *entry) = 0; void DeleteTexture(TexCache::iterator it); + virtual void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) = 0; + virtual bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) = 0; + virtual void BuildTexture(TexCacheEntry *const entry, bool replaceImages) = 0; + bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); // Separate to keep main texture cache size down. diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 1b280be4cf..47c5d6db8d 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -329,59 +329,6 @@ void TextureCacheD3D11::Unbind() { context_->PSSetShaderResources(0, 1, &nullView); } -void TextureCacheD3D11::ApplyTexture() { - TexCacheEntry *entry = nextTexture_; - if (entry == nullptr) { - // Unbind? - return; - } - nextTexture_ = nullptr; - - UpdateMaxSeenV(entry, gstate.isModeThrough()); - - bool replaceImages = false; - if (nextNeedsRebuild_) { - if (nextNeedsRehash_) { - // Update the hash on the texture. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - } - if (nextNeedsChange_) { - // This texture existed previously, let's handle the change. - replaceImages = HandleTextureChange(entry, nextChangeReason_, false, true); - } - - // We actually build afterward (shared with rehash rebuild.) - } else if (nextNeedsRehash_) { - // Okay, this matched and didn't change - but let's check the hash. Maybe it will change. - bool doDelete = true; - if (!CheckFullHash(entry, doDelete)) { - replaceImages = HandleTextureChange(entry, "hash fail", true, doDelete); - nextNeedsRebuild_ = true; - } else if (nextTexture_ != nullptr) { - // Secondary cache picked a different texture, use it. - entry = nextTexture_; - nextTexture_ = nullptr; - UpdateMaxSeenV(entry, gstate.isModeThrough()); - } - } - - // Okay, now actually rebuild the texture if needed. - if (nextNeedsRebuild_) { - BuildTexture(entry, replaceImages); - } - - entry->lastFrame = gpuStats.numFlips; - if (entry->framebuffer) { - ApplyTextureFramebuffer(entry, entry->framebuffer); - } else { - BindTexture(entry); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; - gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; - } -} - class TextureShaderApplierD3D11 { public: struct Pos { diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 824fafe657..55224e0f86 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -65,8 +65,6 @@ public: void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); - void ApplyTexture(); - protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; @@ -79,11 +77,12 @@ private: DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); - void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); - void BuildTexture(TexCacheEntry *const entry, bool replaceImages); + + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; + bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; + void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; ID3D11Device *device_; ID3D11DeviceContext *context_; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index e145ae5708..96aebfb038 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -345,58 +345,6 @@ void TextureCacheDX9::Unbind() { pD3Ddevice->SetTexture(0, NULL); } -void TextureCacheDX9::ApplyTexture() { - TexCacheEntry *entry = nextTexture_; - if (entry == nullptr) { - return; - } - nextTexture_ = nullptr; - - UpdateMaxSeenV(entry, gstate.isModeThrough()); - - bool replaceImages = false; - if (nextNeedsRebuild_) { - if (nextNeedsRehash_) { - // Update the hash on the texture. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - } - if (nextNeedsChange_) { - // This texture existed previously, let's handle the change. - replaceImages = HandleTextureChange(entry, nextChangeReason_, false, true); - } - - // We actually build afterward (shared with rehash rebuild.) - } else if (nextNeedsRehash_) { - // Okay, this matched and didn't change - but let's check the hash. Maybe it will change. - bool doDelete = true; - if (!CheckFullHash(entry, doDelete)) { - replaceImages = HandleTextureChange(entry, "hash fail", true, doDelete); - nextNeedsRebuild_ = true; - } else if (nextTexture_ != nullptr) { - // Secondary cache picked a different texture, use it. - entry = nextTexture_; - nextTexture_ = nullptr; - UpdateMaxSeenV(entry, gstate.isModeThrough()); - } - } - - // Okay, now actually rebuild the texture if needed. - if (nextNeedsRebuild_) { - BuildTexture(entry, replaceImages); - } - - entry->lastFrame = gpuStats.numFlips; - if (entry->framebuffer) { - ApplyTextureFramebuffer(entry, entry->framebuffer); - } else { - BindTexture(entry); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; - gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; - } -} - class TextureShaderApplierDX9 { public: struct Pos { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index dc3ef86183..54f51f8c4b 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -58,8 +58,6 @@ public: void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); - void ApplyTexture(); - protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; @@ -73,11 +71,11 @@ private: D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); - void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); - void BuildTexture(TexCacheEntry *const entry, bool replaceImages); + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; + bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; + void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; LPDIRECT3DTEXTURE9 &DxTex(TexCacheEntry *entry) { return *(LPDIRECT3DTEXTURE9 *)&entry->texturePtr; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6c3684b9a6..a8b8f6c9bd 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -397,57 +397,6 @@ void TextureCacheGLES::Unbind() { glBindTexture(GL_TEXTURE_2D, 0); } -void TextureCacheGLES::ApplyTexture() { - TexCacheEntry *entry = nextTexture_; - if (entry == nullptr) { - return; - } - nextTexture_ = nullptr; - - UpdateMaxSeenV(entry, gstate.isModeThrough()); - - bool replaceImages = false; - if (nextNeedsRebuild_) { - if (nextNeedsRehash_) { - // Update the hash on the texture. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - } - if (nextNeedsChange_) { - // This texture existed previously, let's handle the change. - replaceImages = HandleTextureChange(entry, nextChangeReason_, false, true); - } - // We actually build afterward (shared with rehash rebuild.) - } else if (nextNeedsRehash_) { - // Okay, this matched and didn't change - but let's check the hash. Maybe it will change. - bool doDelete = true; - if (!CheckFullHash(entry, doDelete)) { - replaceImages = HandleTextureChange(entry, "hash fail", true, doDelete); - nextNeedsRebuild_ = true; - } else if (nextTexture_ != nullptr) { - // Secondary cache picked a different texture, use it. - entry = nextTexture_; - nextTexture_ = nullptr; - UpdateMaxSeenV(entry, gstate.isModeThrough()); - } - } - - // Okay, now actually rebuild the texture if needed. - if (nextNeedsRebuild_) { - BuildTexture(entry, replaceImages); - } - - entry->lastFrame = gpuStats.numFlips; - if (entry->framebuffer) { - ApplyTextureFramebuffer(entry, entry->framebuffer); - } else { - BindTexture(entry); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; - gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; - } -} - class TextureShaderApplier { public: struct Pos { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 4993322f98..98277a8475 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -74,8 +74,6 @@ public: void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); - void ApplyTexture(); - protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; @@ -89,10 +87,10 @@ private: void *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); TexCacheEntry::Status CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); - void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); - void BuildTexture(TexCacheEntry *const entry, bool replaceImages); + bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; + void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; std::vector nameCache_; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 0de9df3e0c..589d361bb9 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -415,60 +415,6 @@ void TextureCacheVulkan::Unbind() { sampler_ = VK_NULL_HANDLE; } -void TextureCacheVulkan::ApplyTexture() { - TexCacheEntry *entry = nextTexture_; - if (entry == nullptr) { - // Unbind(); - return; - } - nextTexture_ = nullptr; - - UpdateMaxSeenV(entry, gstate.isModeThrough()); - - if (nextNeedsRebuild_) { - if (nextNeedsRehash_) { - // Update the hash on the texture. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - } - if (nextNeedsChange_) { - // This texture existed previously, let's handle the change. - HandleTextureChange(entry, nextChangeReason_, false, true); - } - - // We actually build afterward (shared with rehash rebuild.) - } else if (nextNeedsRehash_) { - // Okay, this matched and didn't change - but let's check the hash. Maybe it will change. - bool doDelete = true; - if (!CheckFullHash(entry, doDelete)) { - HandleTextureChange(entry, "hash fail", true, doDelete); - nextNeedsRebuild_ = true; - } else if (nextTexture_ != nullptr) { - // Secondary cache picked a different texture, use it. - entry = nextTexture_; - nextTexture_ = nullptr; - UpdateMaxSeenV(entry, gstate.isModeThrough()); - } - } - - // Okay, now actually rebuild the texture if needed. - if (nextNeedsRebuild_) { - BuildTexture(entry); - } - - entry->lastFrame = gpuStats.numFlips; - if (entry->framebuffer) { - ApplyTextureFramebuffer(entry, entry->framebuffer); - } else { - BindTexture(entry); - gstate_c.textureFullAlpha = entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL; - gstate_c.textureSimpleAlpha = entry->GetAlphaStatus() != TexCacheEntry::STATUS_ALPHA_UNKNOWN; - - lastBoundTexture = entry->vkTex; - } -} - void TextureCacheVulkan::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) { DepalShaderVulkan *depal = nullptr; const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); @@ -906,7 +852,7 @@ bool TextureCacheVulkan::HandleTextureChange(TexCacheEntry *const entry, const c return false; } -void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { +void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; // For the estimate, we assume cluts always point to 8888 for simplicity. diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 4014a04498..d11bf68353 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -90,7 +90,6 @@ public: gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } - void ApplyTexture(); void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { imageView = imageView_; sampler = sampler_; @@ -109,12 +108,12 @@ private: VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); - void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); - void BuildTexture(TexCacheEntry *const entry); + void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; + bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; + void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; VulkanContext *vulkan_; VulkanDeviceAllocator *allocator_; From aae2030a14a7eacc20c0d74f15bee239261f1e2b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 23:39:35 +0100 Subject: [PATCH 08/15] Unify Decimate() --- GPU/Common/TextureCacheCommon.cpp | 58 +++++++++++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 3 ++ GPU/D3D11/TextureCacheD3D11.cpp | 60 ---------------------------- GPU/D3D11/TextureCacheD3D11.h | 1 - GPU/Directx9/TextureCacheDX9.cpp | 59 ---------------------------- GPU/Directx9/TextureCacheDX9.h | 1 - GPU/GLES/TextureCacheGLES.cpp | 65 ++----------------------------- GPU/GLES/TextureCacheGLES.h | 1 - GPU/Vulkan/TextureCacheVulkan.cpp | 57 --------------------------- GPU/Vulkan/TextureCacheVulkan.h | 1 - 10 files changed, 64 insertions(+), 242 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 9c00e8a44e..41add61c3b 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -37,6 +37,18 @@ // Videos should be updated every few frames, so we forge quickly. #define VIDEO_DECIMATE_AGE 4 +// If a texture hasn't been seen for this many frames, get rid of it. +#define TEXTURE_KILL_AGE 200 +#define TEXTURE_KILL_AGE_LOWMEM 60 +// Not used in lowmem mode. +#define TEXTURE_SECOND_KILL_AGE 100 + +// Try to be prime to other decimation intervals. +#define TEXCACHE_DECIMATION_INTERVAL 13 + +#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM +#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 + TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw) : draw_(draw), clearCacheNextFrame_(false), @@ -50,6 +62,8 @@ TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw) clutMaxBytes_(0), clutRenderAddress_(0xFFFFFFFF), clutAlphaLinear_(false) { + decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; + // TODO: Clamp down to 256/1KB? Need to check mipmapShareClut and clamp loadclut. clutBufRaw_ = (u32 *)AllocateAlignedMemory(1024 * sizeof(u32), 16); // 4KB clutBufConverted_ = (u32 *)AllocateAlignedMemory(1024 * sizeof(u32), 16); // 4KB @@ -158,6 +172,50 @@ void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) } } +// Removes old textures. +void TextureCacheCommon::Decimate() { + if (--decimationCounter_ <= 0) { + decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; + } else { + return; + } + + if (cacheSizeEstimate_ >= TEXCACHE_MIN_PRESSURE) { + const u32 had = cacheSizeEstimate_; + + ForgetLastTexture(); + int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; + for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { + if (iter->second.lastFrame + killAge < gpuStats.numFlips) { + DeleteTexture(iter++); + } else { + ++iter; + } + } + + VERBOSE_LOG(G3D, "Decimated texture cache, saved %d estimated bytes - now %d bytes", had - cacheSizeEstimate_, cacheSizeEstimate_); + } + + if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { + const u32 had = secondCacheSizeEstimate_; + + for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { + // In low memory mode, we kill them all. + if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { + ReleaseTexture(&iter->second); + secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(&iter->second); + secondCache.erase(iter++); + } else { + ++iter; + } + } + + VERBOSE_LOG(G3D, "Decimated second texture cache, saved %d estimated bytes - now %d bytes", had - secondCacheSizeEstimate_, secondCacheSizeEstimate_); + } + + DecimateVideos(); +} + void TextureCacheCommon::DecimateVideos() { if (!videos_.empty()) { for (auto iter = videos_.begin(); iter != videos_.end(); ) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index ef26104f5e..197ccd02d1 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -45,6 +45,8 @@ enum FramebufferNotification { // Note: only used when hash backoff is disabled. #define TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST 33 +#define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame + struct VirtualFramebuffer; class CachedTextureVulkan; @@ -204,6 +206,7 @@ protected: virtual void Unbind() = 0; virtual void ReleaseTexture(TexCacheEntry *entry) = 0; void DeleteTexture(TexCache::iterator it); + void Decimate(); virtual void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) = 0; virtual bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) = 0; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 47c5d6db8d..801703b41f 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -43,20 +43,6 @@ #define INVALID_TEX (ID3D11ShaderResourceView *)(-1LL) - // If a texture hasn't been seen for this many frames, get rid of it. -#define TEXTURE_KILL_AGE 200 -#define TEXTURE_KILL_AGE_LOWMEM 60 - // Not used in lowmem mode. -#define TEXTURE_SECOND_KILL_AGE 100 - - // Try to be prime to other decimation intervals. -#define TEXCACHE_DECIMATION_INTERVAL 13 - -#define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame - -#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM -#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 - static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12,}, @@ -115,7 +101,6 @@ TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw) context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); lastBoundTexture = INVALID_TEX; - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; HRESULT result = 0; @@ -154,51 +139,6 @@ void TextureCacheD3D11::ForgetLastTexture() { context_->PSSetShaderResources(0, 1, &nullTex); } -// Removes old textures. -void TextureCacheD3D11::Decimate() { - if (--decimationCounter_ <= 0) { - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - if (cacheSizeEstimate_ >= TEXCACHE_MIN_PRESSURE) { - const u32 had = cacheSizeEstimate_; - - ID3D11ShaderResourceView *srv = nullptr; - context_->PSSetShaderResources(0, 1, &srv); - lastBoundTexture = INVALID_TEX; - int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { - if (iter->second.lastFrame + killAge < gpuStats.numFlips) { - DeleteTexture(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated texture cache, saved %d estimated bytes - now %d bytes", had - cacheSizeEstimate_, cacheSizeEstimate_); - } - - if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { - const u32 had = secondCacheSizeEstimate_; - - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { - // In low memory mode, we kill them all. - if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_KILL_AGE < gpuStats.numFlips) { - ReleaseTexture(&iter->second); - secondCache.erase(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated second texture cache, saved %d estimated bytes - now %d bytes", had - secondCacheSizeEstimate_, secondCacheSizeEstimate_); - } - - DecimateVideos(); -} - DXGI_FORMAT getClutDestFormatD3D11(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 55224e0f86..472610aa10 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -71,7 +71,6 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void Decimate(); // Run this once per frame to get rid of old textures. void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 96aebfb038..ac66ea2b99 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -43,20 +43,6 @@ namespace DX9 { #define INVALID_TEX (LPDIRECT3DTEXTURE9)(-1) -// If a texture hasn't been seen for this many frames, get rid of it. -#define TEXTURE_KILL_AGE 200 -#define TEXTURE_KILL_AGE_LOWMEM 60 -// Not used in lowmem mode. -#define TEXTURE_SECOND_KILL_AGE 100 - -// Try to be prime to other decimation intervals. -#define TEXCACHE_DECIMATION_INTERVAL 13 - -#define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame - -#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM -#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 - static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, @@ -66,7 +52,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { TextureCacheDX9::TextureCacheDX9(Draw::DrawContext *draw) : TextureCacheCommon(draw) { lastBoundTexture = INVALID_TEX; - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; D3DCAPS9 pCaps; ZeroMemory(&pCaps, sizeof(pCaps)); @@ -122,50 +107,6 @@ void TextureCacheDX9::ForgetLastTexture() { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } -// Removes old textures. -void TextureCacheDX9::Decimate() { - if (--decimationCounter_ <= 0) { - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - if (cacheSizeEstimate_ >= TEXCACHE_MIN_PRESSURE) { - const u32 had = cacheSizeEstimate_; - - pD3Ddevice->SetTexture(0, NULL); - lastBoundTexture = INVALID_TEX; - int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { - if (iter->second.lastFrame + killAge < gpuStats.numFlips) { - DeleteTexture(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated texture cache, saved %d estimated bytes - now %d bytes", had - cacheSizeEstimate_, cacheSizeEstimate_); - } - - if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { - const u32 had = secondCacheSizeEstimate_; - - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { - // In low memory mode, we kill them all. - if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_KILL_AGE < gpuStats.numFlips) { - ReleaseTexture(&iter->second); - secondCache.erase(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated second texture cache, saved %d estimated bytes - now %d bytes", had - secondCacheSizeEstimate_, secondCacheSizeEstimate_); - } - - DecimateVideos(); -} - D3DFORMAT getClutDestFormat(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 54f51f8c4b..2eb96b8dc7 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -64,7 +64,6 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void Decimate(); // Run this once per frame to get rid of old textures. void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, bool force); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index a8b8f6c9bd..08867fe599 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -43,33 +43,18 @@ #include #endif -// If a texture hasn't been seen for this many frames, get rid of it. -#define TEXTURE_KILL_AGE 200 -#define TEXTURE_KILL_AGE_LOWMEM 60 -// Not used in lowmem mode. -#define TEXTURE_SECOND_KILL_AGE 100 - -// Try to be prime to other decimation intervals. -#define TEXCACHE_DECIMATION_INTERVAL 13 - -#define TEXCACHE_NAME_CACHE_SIZE 16 - -#define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame - -#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in GL -#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 - #ifndef GL_UNPACK_ROW_LENGTH #define GL_UNPACK_ROW_LENGTH 0x0CF2 #endif #define INVALID_TEX -1 +#define TEXCACHE_NAME_CACHE_SIZE 16 + TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw) : TextureCacheCommon(draw) { timesInvalidatedAllThisFrame_ = 0; lastBoundTexture = INVALID_TEX; - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyLevel); SetupTextureDecoder(); @@ -101,51 +86,6 @@ void TextureCacheGLES::Clear(bool delete_them) { } } -// Removes old textures. -void TextureCacheGLES::Decimate() { - if (--decimationCounter_ <= 0) { - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - if (cacheSizeEstimate_ >= TEXCACHE_MIN_PRESSURE) { - const u32 had = cacheSizeEstimate_; - - glBindTexture(GL_TEXTURE_2D, 0); - lastBoundTexture = INVALID_TEX; - int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { - if (iter->second.lastFrame + killAge < gpuStats.numFlips) { - DeleteTexture(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated texture cache, saved %d estimated bytes - now %d bytes", had - cacheSizeEstimate_, cacheSizeEstimate_); - } - - if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { - const u32 had = secondCacheSizeEstimate_; - - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { - // In low memory mode, we kill them all. - if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { - glDeleteTextures(1, &iter->second.textureName); - secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(&iter->second); - secondCache.erase(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated second texture cache, saved %d estimated bytes - now %d bytes", had - secondCacheSizeEstimate_, secondCacheSizeEstimate_); - } - - DecimateVideos(); -} - GLenum getClutDestFormat(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: @@ -616,6 +556,7 @@ void TextureCacheGLES::SetTexture(bool force) { u32 texaddr = gstate.getTextureAddress(level); if (!Memory::IsValidAddress(texaddr)) { // Bind a null texture and return. + Unbind(); glBindTexture(GL_TEXTURE_2D, 0); lastBoundTexture = INVALID_TEX; return; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 98277a8475..0d3fa241a6 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -80,7 +80,6 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void Decimate(); // Run this once per frame to get rid of old textures. void UpdateSamplingParams(TexCacheEntry &entry, bool force); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, bool replaceImages, int scaleFactor, GLenum dstFmt); GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 589d361bb9..f276777263 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -48,22 +48,10 @@ #include #endif -// If a texture hasn't been seen for this many frames, get rid of it. -#define TEXTURE_KILL_AGE 200 -#define TEXTURE_KILL_AGE_LOWMEM 60 -// Not used in lowmem mode. -#define TEXTURE_SECOND_KILL_AGE 100 - -// Try to be prime to other decimation intervals. -#define TEXCACHE_DECIMATION_INTERVAL 13 - #define TEXCACHE_NAME_CACHE_SIZE 16 #define TEXCACHE_MAX_TEXELS_SCALED (256*256) // Per frame -#define TEXCACHE_MIN_PRESSURE (16 * 1024 * 1024) // Total in GL -#define TEXCACHE_SECOND_MIN_PRESSURE (4 * 1024 * 1024) - #define TEXCACHE_MIN_SLAB_SIZE (4 * 1024 * 1024) #define TEXCACHE_MAX_SLAB_SIZE (32 * 1024 * 1024) @@ -144,7 +132,6 @@ TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *v texelsScaledThisFrame_(0) { timesInvalidatedAllThisFrame_ = 0; lastBoundTexture = nullptr; - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE); SetupTextureDecoder(); @@ -208,50 +195,6 @@ void TextureCacheVulkan::DeleteTexture(TexCache::iterator it) { cache.erase(it); } -// Removes old textures. -void TextureCacheVulkan::Decimate() { - if (--decimationCounter_ <= 0) { - decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; - } else { - return; - } - - if (cacheSizeEstimate_ >= TEXCACHE_MIN_PRESSURE) { - const u32 had = cacheSizeEstimate_; - - lastBoundTexture = nullptr; - int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { - if (iter->second.lastFrame + killAge < gpuStats.numFlips) { - DeleteTexture(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated texture cache, saved %d estimated bytes - now %d bytes", had - cacheSizeEstimate_, cacheSizeEstimate_); - } - - if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { - const u32 had = secondCacheSizeEstimate_; - - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { - // In low memory mode, we kill them all. - if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { - delete iter->second.vkTex; - secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(&iter->second); - secondCache.erase(iter++); - } else { - ++iter; - } - } - - VERBOSE_LOG(G3D, "Decimated second texture cache, saved %d estimated bytes - now %d bytes", had - secondCacheSizeEstimate_, secondCacheSizeEstimate_); - } - - DecimateVideos(); -} - VkFormat getClutDestFormatVulkan(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index d11bf68353..fe103e36f8 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -101,7 +101,6 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void Decimate(); // Run this once per frame to get rid of old textures. void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt); From e24e652b0d929d62ef2f2f5083acf074034580b4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Feb 2017 23:50:04 +0100 Subject: [PATCH 09/15] Prepare to unify SetTexture --- GPU/Common/TextureCacheCommon.h | 1 + GPU/D3D11/TextureCacheD3D11.cpp | 4 ++++ GPU/D3D11/TextureCacheD3D11.h | 1 + GPU/Directx9/TextureCacheDX9.cpp | 8 ++++++-- GPU/Directx9/TextureCacheDX9.h | 1 + GPU/GLES/TextureCacheGLES.cpp | 9 +++------ GPU/GLES/TextureCacheGLES.h | 7 ++++++- GPU/Vulkan/TextureCacheVulkan.h | 3 +++ 8 files changed, 25 insertions(+), 9 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 197ccd02d1..67452014a1 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -184,6 +184,7 @@ public: void ClearNextFrame(); virtual void ForgetLastTexture() = 0; + virtual void InvalidateLastTexture() = 0; virtual void Clear(bool delete_them); // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 801703b41f..da6c523c37 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -139,6 +139,10 @@ void TextureCacheD3D11::ForgetLastTexture() { context_->PSSetShaderResources(0, 1, &nullTex); } +void TextureCacheD3D11::InvalidateLastTexture() { + lastBoundTexture = INVALID_TEX; +} + DXGI_FORMAT getClutDestFormatD3D11(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 472610aa10..6f086ee90d 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -62,6 +62,7 @@ public: bool DecodeTexture(u8 *output, const GPUgstate &state); void ForgetLastTexture() override; + void InvalidateLastTexture() override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index ac66ea2b99..86a3eecfe8 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -107,6 +107,10 @@ void TextureCacheDX9::ForgetLastTexture() { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } +void TextureCacheDX9::InvalidateLastTexture() { + lastBoundTexture = INVALID_TEX; +} + D3DFORMAT getClutDestFormat(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: @@ -467,13 +471,13 @@ void TextureCacheDX9::SetTexture(bool force) { #ifdef DEBUG_TEXTURES if (SetDebugTexture()) { // A different texture was bound, let's rebind next time. - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); return; } #endif if (force) { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); } u8 level = 0; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 2eb96b8dc7..7d0cf5b345 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -55,6 +55,7 @@ public: bool DecodeTexture(u8 *output, const GPUgstate &state); void ForgetLastTexture() override; + void InvalidateLastTexture() override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 08867fe599..cb81c8271a 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -47,8 +47,6 @@ #define GL_UNPACK_ROW_LENGTH 0x0CF2 #endif -#define INVALID_TEX -1 - #define TEXCACHE_NAME_CACHE_SIZE 16 TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw) @@ -541,13 +539,13 @@ void TextureCacheGLES::SetTexture(bool force) { #ifdef DEBUG_TEXTURES if (SetDebugTexture()) { // A different texture was bound, let's rebind next time. - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); return; } #endif if (force) { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); } u8 level = 0; @@ -557,7 +555,6 @@ void TextureCacheGLES::SetTexture(bool force) { if (!Memory::IsValidAddress(texaddr)) { // Bind a null texture and return. Unbind(); - glBindTexture(GL_TEXTURE_2D, 0); lastBoundTexture = INVALID_TEX; return; } @@ -768,7 +765,7 @@ bool TextureCacheGLES::HandleTextureChange(TexCacheEntry *const entry, const cha if (entry->textureName == lastBoundTexture) { lastBoundTexture = INVALID_TEX; } - glDeleteTextures(1, &entry->textureName); + ReleaseTexture(entry); entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; } } diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 0d3fa241a6..9da5020017 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -63,9 +63,12 @@ public: } void ForgetLastTexture() override { - lastBoundTexture = -1; + lastBoundTexture = INVALID_TEX; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } + void InvalidateLastTexture() override { + lastBoundTexture = INVALID_TEX; + } u32 AllocTextureName(); @@ -102,6 +105,8 @@ private: DepalShaderCacheGLES *depalShaderCache_; ShaderManagerGLES *shaderManager_; DrawEngineGLES *drawEngine_; + + enum { INVALID_TEX = -1 }; }; GLenum getClutDestFormat(GEPaletteFormat format); diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index fe103e36f8..3041677b9f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -89,6 +89,9 @@ public: lastBoundTexture = nullptr; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } + void InvalidateLastTexture() override { + lastBoundTexture = nullptr; + } void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { imageView = imageView_; From f15e25c4b5517d29e7313ea93538669e85b6c00e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:05:23 +0100 Subject: [PATCH 10/15] Centralize SetTexture --- GPU/Common/TextureCacheCommon.cpp | 217 ++++++++++++++++++++++++++++- GPU/Common/TextureCacheCommon.h | 9 +- GPU/D3D11/TextureCacheD3D11.cpp | 219 +---------------------------- GPU/D3D11/TextureCacheD3D11.h | 4 +- GPU/Directx9/TextureCacheDX9.cpp | 221 +----------------------------- GPU/Directx9/TextureCacheDX9.h | 3 +- GPU/GLES/TextureCacheGLES.cpp | 218 ----------------------------- GPU/GLES/TextureCacheGLES.h | 4 +- GPU/Vulkan/TextureCacheVulkan.cpp | 216 ----------------------------- GPU/Vulkan/TextureCacheVulkan.h | 3 +- 10 files changed, 230 insertions(+), 884 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 41add61c3b..fcac96f6a6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -61,7 +61,8 @@ TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw) clutTotalBytes_(0), clutMaxBytes_(0), clutRenderAddress_(0xFFFFFFFF), - clutAlphaLinear_(false) { + clutAlphaLinear_(false), + isBgraBackend_(false) { decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; // TODO: Clamp down to 256/1KB? Need to check mipmapShareClut and clamp loadclut. @@ -172,6 +173,220 @@ void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) } } + +void TextureCacheCommon::SetTexture(bool force) { +#ifdef DEBUG_TEXTURES + if (SetDebugTexture()) { + // A different texture was bound, let's rebind next time. + InvalidateLastTexture(); + return; + } +#endif + + if (force) { + InvalidateLastTexture(); + } + + u8 level = 0; + if (IsFakeMipmapChange()) + level = (gstate.texlevel >> 20) & 0xF; + u32 texaddr = gstate.getTextureAddress(level); + if (!Memory::IsValidAddress(texaddr)) { + // Bind a null texture and return. + Unbind(); + InvalidateLastTexture(); + return; + } + + const u16 dim = gstate.getTextureDimension(level); + int w = gstate.getTextureWidth(level); + int h = gstate.getTextureHeight(level); + + GETextureFormat format = gstate.getTextureFormat(); + if (format >= 11) { + ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); + // TODO: Better assumption? + format = GE_TFMT_5650; + } + bool hasClut = gstate.isTextureFormatIndexed(); + + // Ignore uncached/kernel when caching. + u32 cluthash; + if (hasClut) { + if (clutLastFormat_ != gstate.clutformat) { + // We update here because the clut format can be specified after the load. + UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); + } + cluthash = clutHash_ ^ gstate.clutformat; + } else { + cluthash = 0; + } + u64 cachekey = TexCacheEntry::CacheKey(texaddr, format, dim, cluthash); + + int bufw = GetTextureBufw(0, texaddr, format); + u8 maxLevel = gstate.getTextureMaxLevel(); + + u32 texhash = MiniHash((const u32 *)Memory::GetPointerUnchecked(texaddr)); + + TexCache::iterator iter = cache.find(cachekey); + TexCacheEntry *entry = NULL; + gstate_c.needShaderTexClamp = false; + gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; + gstate_c.bgraTexture = isBgraBackend_; + + if (iter != cache.end()) { + entry = &iter->second; + // Validate the texture still matches the cache entry. + bool match = entry->Matches(dim, format, maxLevel); + const char *reason = "different params"; + + // Check for FBO - slow! + if (entry->framebuffer) { + if (match) { + if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { + WARN_LOG_REPORT_ONCE(clutAndTexRender, G3D, "Using rendered texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); + } + + SetTextureFramebuffer(entry, entry->framebuffer); + return; + } else { + // Make sure we re-evaluate framebuffers. + DetachFramebuffer(entry, texaddr, entry->framebuffer); + reason = "detached framebuf"; + match = false; + } + } + + bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE; + + // First let's see if another texture with the same address had a hashfail. + if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) { + // Always rehash in this case, if one changed the rest all probably did. + rehash = true; + entry->status &= ~TexCacheEntry::STATUS_CLUT_RECHECK; + } else if (!gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE)) { + // Okay, just some parameter change - the data didn't change, no need to rehash. + rehash = false; + } + + if (match) { + if (entry->lastFrame != gpuStats.numFlips) { + u32 diff = gpuStats.numFlips - entry->lastFrame; + entry->numFrames++; + + if (entry->framesUntilNextFullHash < diff) { + // Exponential backoff up to 512 frames. Textures are often reused. + if (entry->numFrames > 32) { + // Also, try to add some "randomness" to avoid rehashing several textures the same frame. + entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (entry->textureName & 15); + } else { + entry->framesUntilNextFullHash = entry->numFrames; + } + rehash = true; + } else { + entry->framesUntilNextFullHash -= diff; + } + } + + // If it's not huge or has been invalidated many times, recheck the whole texture. + if (entry->invalidHint > 180 || (entry->invalidHint > 15 && (dim >> 8) < 9 && (dim & 0xF) < 9)) { + entry->invalidHint = 0; + rehash = true; + } + + if (texhash != entry->hash) { + match = false; + } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { + rehash = false; + } + } + + if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { + if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { + // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); + match = false; + reason = "scaling"; + } + } + + if (match) { + // TODO: Mark the entry reliable if it's been safe for long enough? + //got one! + gstate_c.curTextureWidth = w; + gstate_c.curTextureHeight = h; + if (rehash) { + // Update in case any of these changed. + entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; + entry->bufw = bufw; + entry->cluthash = cluthash; + } + + nextTexture_ = entry; + nextNeedsRehash_ = rehash; + nextNeedsChange_ = false; + // Might need a rebuild if the hash fails. + nextNeedsRebuild_ = false; + VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); + return; //Done! + } else { + nextChangeReason_ = reason; + nextNeedsChange_ = true; + } + } else { + VERBOSE_LOG(G3D, "No texture in cache, decoding..."); + TexCacheEntry entryNew = { 0 }; + cache[cachekey] = entryNew; + + if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { + WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); + } + + entry = &cache[cachekey]; + if (g_Config.bTextureBackoffCache) { + entry->status = TexCacheEntry::STATUS_HASHING; + } else { + entry->status = TexCacheEntry::STATUS_UNRELIABLE; + } + + nextNeedsChange_ = false; + } + + // We have to decode it, let's setup the cache entry first. + entry->addr = texaddr; + entry->hash = texhash; + entry->dim = dim; + entry->format = format; + entry->maxLevel = maxLevel; + + // This would overestimate the size in many case so we underestimate instead + // to avoid excessive clearing caused by cache invalidations. + entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; + entry->bufw = bufw; + + entry->cluthash = cluthash; + + gstate_c.curTextureWidth = w; + gstate_c.curTextureHeight = h; + + // Before we go reading the texture from memory, let's check for render-to-texture. + // We must do this early so we have the right w/h. + entry->framebuffer = 0; + for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { + auto framebuffer = fbCache_[i]; + AttachFramebuffer(entry, framebuffer->fb_address, framebuffer); + } + + // If we ended up with a framebuffer, attach it - no texture decoding needed. + if (entry->framebuffer) { + SetTextureFramebuffer(entry, entry->framebuffer); + } + + nextTexture_ = entry; + nextNeedsRehash_ = entry->framebuffer == nullptr; + // We still need to rebuild, to allocate a texture. But we'll bail early. + nextNeedsRebuild_ = true; +} + // Removes old textures. void TextureCacheCommon::Decimate() { if (--decimationCounter_ <= 0) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 67452014a1..27fcbd9575 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -177,6 +177,7 @@ public: void LoadClut(u32 clutAddr, u32 loadBytes); bool GetCurrentClutBuffer(GPUDebugBuffer &buffer); + void SetTexture(bool force = false); void ApplyTexture(); bool SetOffsetTexture(u32 offset); void Invalidate(u32 addr, int size, GPUInvalidationType type); @@ -212,7 +213,7 @@ protected: virtual void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) = 0; virtual bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) = 0; virtual void BuildTexture(TexCacheEntry *const entry, bool replaceImages) = 0; - + virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0; bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); // Separate to keep main texture cache size down. @@ -262,6 +263,10 @@ protected: } } + static inline u32 MiniHash(const u32 *ptr) { + return ptr[0]; + } + Draw::DrawContext *draw_; TextureReplacer replacer; FramebufferManagerCommon *framebufferManager_; @@ -312,6 +317,8 @@ protected: bool nextNeedsRehash_; bool nextNeedsChange_; bool nextNeedsRebuild_; + + bool isBgraBackend_; }; inline bool TexCacheEntry::Matches(u16 dim2, u8 format2, u8 maxLevel2) const { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index da6c523c37..25f6dadd4c 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -100,6 +100,7 @@ TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw) device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + isBgraBackend_ = true; lastBoundTexture = INVALID_TEX; HRESULT result = 0; @@ -219,10 +220,6 @@ void TextureCacheD3D11::StartFrame() { } } -static inline u32 MiniHash(const u32 *ptr) { - return ptr[0]; -} - void TextureCacheD3D11::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutBase * (clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. @@ -447,220 +444,6 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra lastBoundTexture = INVALID_TEX; } -void TextureCacheD3D11::SetTexture(bool force) { -#ifdef DEBUG_TEXTURES - if (SetDebugTexture()) { - // A different texture was bound, let's rebind next time. - lastBoundTexture = INVALID_TEX; - return; - } -#endif - - if (force) { - lastBoundTexture = INVALID_TEX; - } - - u32 texaddr = gstate.getTextureAddress(0); - if (!Memory::IsValidAddress(texaddr)) { - // Bind a null texture and return. - ID3D11ShaderResourceView *srv = nullptr; - context_->PSSetShaderResources(0, 1, &srv); - lastBoundTexture = INVALID_TEX; - return; - } - - const u16 dim = gstate.getTextureDimension(0); - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - - GETextureFormat format = gstate.getTextureFormat(); - if (format >= 11) { - ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); - // TODO: Better assumption? - format = GE_TFMT_5650; - } - bool hasClut = gstate.isTextureFormatIndexed(); - - // Ignore uncached/kernel when caching. - u32 cluthash; - if (hasClut) { - if (clutLastFormat_ != gstate.clutformat) { - // We update here because the clut format can be specified after the load. - UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); - } - cluthash = clutHash_ ^ gstate.clutformat; - } else { - cluthash = 0; - } - u64 cachekey = TexCacheEntry::CacheKey(texaddr, format, dim, cluthash); - - int bufw = GetTextureBufw(0, texaddr, format); - u8 maxLevel = gstate.getTextureMaxLevel(); - - u32 texhash = MiniHash((const u32 *)Memory::GetPointer(texaddr)); - - TexCache::iterator iter = cache.find(cachekey); - TexCacheEntry *entry = NULL; - gstate_c.needShaderTexClamp = false; - gstate_c.bgraTexture = true; - gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; - bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; - - if (iter != cache.end()) { - entry = &iter->second; - // Validate the texture still matches the cache entry. - bool match = entry->Matches(dim, format, maxLevel); - const char *reason = "different params"; - - // Check for FBO - slow! - if (entry->framebuffer) { - if (match) { - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutAndTexRender, G3D, "Using rendered texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - SetTextureFramebuffer(entry, entry->framebuffer); - return; - } else { - // Make sure we re-evaluate framebuffers. - DetachFramebuffer(entry, texaddr, entry->framebuffer); - reason = "detached framebuf"; - match = false; - } - } - - bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE; - - // First let's see if another texture with the same address had a hashfail. - if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) { - // Always rehash in this case, if one changed the rest all probably did. - rehash = true; - entry->status &= ~TexCacheEntry::STATUS_CLUT_RECHECK; - } else if (!gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE)) { - // Okay, just some parameter change - the data didn't change, no need to rehash. - rehash = false; - } - - if (match) { - if (entry->lastFrame != gpuStats.numFlips) { - u32 diff = gpuStats.numFlips - entry->lastFrame; - entry->numFrames++; - - if (entry->framesUntilNextFullHash < diff) { - // Exponential backoff up to 512 frames. Textures are often reused. - if (entry->numFrames > 32) { - // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + ((intptr_t)entry->texturePtr & 15); - } else { - entry->framesUntilNextFullHash = entry->numFrames; - } - rehash = true; - } else { - entry->framesUntilNextFullHash -= diff; - } - } - - // If it's not huge or has been invalidated many times, recheck the whole texture. - if (entry->invalidHint > 180 || (entry->invalidHint > 15 && (dim >> 8) < 9 && (dim & 0xF) < 9)) { - entry->invalidHint = 0; - rehash = true; - } - - if (texhash != entry->hash) { - match = false; - } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - rehash = false; - } - } - - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { - if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); - match = false; - reason = "scaling"; - } - } - - if (match) { - // TODO: Mark the entry reliable if it's been safe for long enough? - //got one! - if (entry->texturePtr != lastBoundTexture) { - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - } - if (rehash) { - // Update in case any of these changed. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - entry->cluthash = cluthash; - } - - nextTexture_ = entry; - nextNeedsRehash_ = rehash; - nextNeedsChange_ = false; - // Might need a rebuild if the hash fails. - nextNeedsRebuild_ = false; - VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); - return; //Done! - } else { - nextChangeReason_ = reason; - nextNeedsChange_ = true; - } - } else { - VERBOSE_LOG(G3D, "No texture in cache, decoding..."); - TexCacheEntry entryNew = { 0 }; - cache[cachekey] = entryNew; - - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - entry = &cache[cachekey]; - if (g_Config.bTextureBackoffCache) { - entry->status = TexCacheEntry::STATUS_HASHING; - } else { - entry->status = TexCacheEntry::STATUS_UNRELIABLE; - } - - nextNeedsChange_ = false; - } - - // We have to decode it, let's setup the cache entry first. - entry->addr = texaddr; - entry->hash = texhash; - entry->dim = dim; - entry->format = format; - entry->maxLevel = maxLevel; - - // This would overestimate the size in many case so we underestimate instead - // to avoid excessive clearing caused by cache invalidations. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - - entry->cluthash = cluthash; - - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - - // Before we go reading the texture from memory, let's check for render-to-texture. - // We must do this early so we have the right w/h. - entry->framebuffer = 0; - for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { - auto framebuffer = fbCache_[i]; - AttachFramebuffer(entry, framebuffer->fb_address, framebuffer); - } - - // If we ended up with a framebuffer, attach it - no texture decoding needed. - if (entry->framebuffer) { - SetTextureFramebuffer(entry, entry->framebuffer); - } - - nextTexture_ = entry; - nextNeedsRehash_ = entry->framebuffer == nullptr; - // We still need to rebuild, to allocate a texture. But we'll bail early. - nextNeedsRebuild_ = true; -} - bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 6f086ee90d..4f1c4aa6a9 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -46,8 +46,6 @@ public: TextureCacheD3D11(Draw::DrawContext *draw); ~TextureCacheD3D11(); - void SetTexture(bool force = false); - void StartFrame(); void SetFramebufferManager(FramebufferManagerD3D11 *fbManager); @@ -76,7 +74,7 @@ private: void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); - void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); + void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 86a3eecfe8..57da0cda9b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -52,6 +52,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { TextureCacheDX9::TextureCacheDX9(Draw::DrawContext *draw) : TextureCacheCommon(draw) { lastBoundTexture = INVALID_TEX; + isBgraBackend_ = true; D3DCAPS9 pCaps; ZeroMemory(&pCaps, sizeof(pCaps)); @@ -240,10 +241,6 @@ void TextureCacheDX9::StartFrame() { } -static inline u32 MiniHash(const u32 *ptr) { - return ptr[0]; -} - void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutBase * (clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. @@ -467,222 +464,6 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame lastBoundTexture = INVALID_TEX; } -void TextureCacheDX9::SetTexture(bool force) { -#ifdef DEBUG_TEXTURES - if (SetDebugTexture()) { - // A different texture was bound, let's rebind next time. - InvalidateLastTexture(); - return; - } -#endif - - if (force) { - InvalidateLastTexture(); - } - - u8 level = 0; - if (IsFakeMipmapChange()) - level = (gstate.texlevel >> 20) & 0xF; - u32 texaddr = gstate.getTextureAddress(level); - if (!Memory::IsValidAddress(texaddr)) { - // Bind a null texture and return. - pD3Ddevice->SetTexture(0, NULL); - lastBoundTexture = INVALID_TEX; - return; - } - - const u16 dim = gstate.getTextureDimension(level); - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); - - GETextureFormat format = gstate.getTextureFormat(); - if (format >= 11) { - ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); - // TODO: Better assumption? - format = GE_TFMT_5650; - } - bool hasClut = gstate.isTextureFormatIndexed(); - - // Ignore uncached/kernel when caching. - u32 cluthash; - if (hasClut) { - if (clutLastFormat_ != gstate.clutformat) { - // We update here because the clut format can be specified after the load. - UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); - } - cluthash = clutHash_ ^ gstate.clutformat; - } else { - cluthash = 0; - } - u64 cachekey = TexCacheEntry::CacheKey(texaddr, format, dim, cluthash); - - int bufw = GetTextureBufw(0, texaddr, format); - u8 maxLevel = gstate.getTextureMaxLevel(); - - u32 texhash = MiniHash((const u32 *)Memory::GetPointer(texaddr)); - - TexCache::iterator iter = cache.find(cachekey); - TexCacheEntry *entry = NULL; - gstate_c.needShaderTexClamp = false; - gstate_c.bgraTexture = true; - gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; - bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; - - if (iter != cache.end()) { - entry = &iter->second; - // Validate the texture still matches the cache entry. - bool match = entry->Matches(dim, format, maxLevel); - const char *reason = "different params"; - - // Check for FBO - slow! - if (entry->framebuffer) { - if (match) { - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutAndTexRender, G3D, "Using rendered texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - SetTextureFramebuffer(entry, entry->framebuffer); - return; - } else { - // Make sure we re-evaluate framebuffers. - DetachFramebuffer(entry, texaddr, entry->framebuffer); - reason = "detached framebuf"; - match = false; - } - } - - bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE; - - // First let's see if another texture with the same address had a hashfail. - if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) { - // Always rehash in this case, if one changed the rest all probably did. - rehash = true; - entry->status &= ~TexCacheEntry::STATUS_CLUT_RECHECK; - } else if (!gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE)) { - // Okay, just some parameter change - the data didn't change, no need to rehash. - rehash = false; - } - - if (match) { - if (entry->lastFrame != gpuStats.numFlips) { - u32 diff = gpuStats.numFlips - entry->lastFrame; - entry->numFrames++; - - if (entry->framesUntilNextFullHash < diff) { - // Exponential backoff up to 512 frames. Textures are often reused. - if (entry->numFrames > 32) { - // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + ((intptr_t)entry->texturePtr & 15); - } else { - entry->framesUntilNextFullHash = entry->numFrames; - } - rehash = true; - } else { - entry->framesUntilNextFullHash -= diff; - } - } - - // If it's not huge or has been invalidated many times, recheck the whole texture. - if (entry->invalidHint > 180 || (entry->invalidHint > 15 && (dim >> 8) < 9 && (dim & 0xF) < 9)) { - entry->invalidHint = 0; - rehash = true; - } - - if (texhash != entry->hash) { - match = false; - } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - rehash = false; - } - } - - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { - if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); - match = false; - reason = "scaling"; - } - } - - if (match) { - // TODO: Mark the entry reliable if it's been safe for long enough? - //got one! - if (entry->texturePtr != lastBoundTexture) { - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - } - if (rehash) { - // Update in case any of these changed. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - entry->cluthash = cluthash; - } - - nextTexture_ = entry; - nextNeedsRehash_ = rehash; - nextNeedsChange_ = false; - // Might need a rebuild if the hash fails. - nextNeedsRebuild_= false; - VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); - return; //Done! - } else { - nextChangeReason_ = reason; - nextNeedsChange_ = true; - } - } else { - VERBOSE_LOG(G3D, "No texture in cache, decoding..."); - TexCacheEntry entryNew = {0}; - cache[cachekey] = entryNew; - - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - entry = &cache[cachekey]; - if (g_Config.bTextureBackoffCache) { - entry->status = TexCacheEntry::STATUS_HASHING; - } else { - entry->status = TexCacheEntry::STATUS_UNRELIABLE; - } - - nextNeedsChange_ = false; - } - - // We have to decode it, let's setup the cache entry first. - entry->addr = texaddr; - entry->hash = texhash; - entry->dim = dim; - entry->format = format; - entry->maxLevel = maxLevel; - - // This would overestimate the size in many case so we underestimate instead - // to avoid excessive clearing caused by cache invalidations. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - - entry->cluthash = cluthash; - - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - - // Before we go reading the texture from memory, let's check for render-to-texture. - // We must do this early so we have the right w/h. - entry->framebuffer = 0; - for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { - auto framebuffer = fbCache_[i]; - AttachFramebuffer(entry, framebuffer->fb_address, framebuffer); - } - - // If we ended up with a framebuffer, attach it - no texture decoding needed. - if (entry->framebuffer) { - SetTextureFramebuffer(entry, entry->framebuffer); - } - - nextTexture_ = entry; - nextNeedsRehash_ = entry->framebuffer == nullptr; - // We still need to rebuild, to allocate a texture. But we'll bail early. - nextNeedsRebuild_= true; -} - bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 7d0cf5b345..7e5f88a076 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -40,7 +40,6 @@ public: TextureCacheDX9(Draw::DrawContext *draw); ~TextureCacheDX9(); - void SetTexture(bool force = false); void StartFrame(); void SetFramebufferManager(FramebufferManagerDX9 *fbManager); @@ -70,7 +69,7 @@ private: void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); - void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); + void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index cb81c8271a..dd2c1bec6b 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -236,10 +236,6 @@ void TextureCacheGLES::StartFrame() { } } -static inline u32 MiniHash(const u32 *ptr) { - return ptr[0]; -} - void TextureCacheGLES::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutFormat == GE_CMODE_32BIT_ABGR8888 ? (clutBase * sizeof(u32)) : (clutBase * sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. @@ -535,220 +531,6 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) { } } -void TextureCacheGLES::SetTexture(bool force) { -#ifdef DEBUG_TEXTURES - if (SetDebugTexture()) { - // A different texture was bound, let's rebind next time. - InvalidateLastTexture(); - return; - } -#endif - - if (force) { - InvalidateLastTexture(); - } - - u8 level = 0; - if (IsFakeMipmapChange()) - level = (gstate.texlevel >> 20) & 0xF; - u32 texaddr = gstate.getTextureAddress(level); - if (!Memory::IsValidAddress(texaddr)) { - // Bind a null texture and return. - Unbind(); - lastBoundTexture = INVALID_TEX; - return; - } - - const u16 dim = gstate.getTextureDimension(level); - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); - - GETextureFormat format = gstate.getTextureFormat(); - if (format >= 11) { - ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); - // TODO: Better assumption? - format = GE_TFMT_5650; - } - bool hasClut = gstate.isTextureFormatIndexed(); - - // Ignore uncached/kernel when caching. - u32 cluthash; - if (hasClut) { - if (clutLastFormat_ != gstate.clutformat) { - // We update here because the clut format can be specified after the load. - UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); - } - cluthash = clutHash_ ^ gstate.clutformat; - } else { - cluthash = 0; - } - u64 cachekey = TexCacheEntry::CacheKey(texaddr, format, dim, cluthash); - - int bufw = GetTextureBufw(0, texaddr, format); - u8 maxLevel = gstate.getTextureMaxLevel(); - - u32 texhash = MiniHash((const u32 *)Memory::GetPointerUnchecked(texaddr)); - - TexCache::iterator iter = cache.find(cachekey); - TexCacheEntry *entry = NULL; - gstate_c.needShaderTexClamp = false; - gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; - - if (iter != cache.end()) { - entry = &iter->second; - // Validate the texture still matches the cache entry. - bool match = entry->Matches(dim, format, maxLevel); - const char *reason = "different params"; - - // Check for FBO - slow! - if (entry->framebuffer) { - if (match) { - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutAndTexRender, G3D, "Using rendered texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - SetTextureFramebuffer(entry, entry->framebuffer); - return; - } else { - // Make sure we re-evaluate framebuffers. - DetachFramebuffer(entry, texaddr, entry->framebuffer); - reason = "detached framebuf"; - match = false; - } - } - - bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE; - - // First let's see if another texture with the same address had a hashfail. - if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) { - // Always rehash in this case, if one changed the rest all probably did. - rehash = true; - entry->status &= ~TexCacheEntry::STATUS_CLUT_RECHECK; - } else if (!gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE)) { - // Okay, just some parameter change - the data didn't change, no need to rehash. - rehash = false; - } - - if (match) { - if (entry->lastFrame != gpuStats.numFlips) { - u32 diff = gpuStats.numFlips - entry->lastFrame; - entry->numFrames++; - - if (entry->framesUntilNextFullHash < diff) { - // Exponential backoff up to 512 frames. Textures are often reused. - if (entry->numFrames > 32) { - // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (entry->textureName & 15); - } else { - entry->framesUntilNextFullHash = entry->numFrames; - } - rehash = true; - } else { - entry->framesUntilNextFullHash -= diff; - } - } - - // If it's not huge or has been invalidated many times, recheck the whole texture. - if (entry->invalidHint > 180 || (entry->invalidHint > 15 && (dim >> 8) < 9 && (dim & 0xF) < 9)) { - entry->invalidHint = 0; - rehash = true; - } - - if (texhash != entry->hash) { - match = false; - } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - rehash = false; - } - } - - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { - if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); - match = false; - reason = "scaling"; - } - } - - if (match) { - // TODO: Mark the entry reliable if it's been safe for long enough? - //got one! - if (entry->textureName != lastBoundTexture) { - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - } - if (rehash) { - // Update in case any of these changed. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - entry->cluthash = cluthash; - } - - nextTexture_ = entry; - nextNeedsRehash_ = rehash; - nextNeedsChange_ = false; - // Might need a rebuild if the hash fails. - nextNeedsRebuild_= false; - VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); - return; //Done! - } else { - nextChangeReason_ = reason; - nextNeedsChange_ = true; - } - } else { - VERBOSE_LOG(G3D, "No texture in cache, decoding..."); - TexCacheEntry entryNew = {0}; - cache[cachekey] = entryNew; - - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - entry = &cache[cachekey]; - if (g_Config.bTextureBackoffCache) { - entry->status = TexCacheEntry::STATUS_HASHING; - } else { - entry->status = TexCacheEntry::STATUS_UNRELIABLE; - } - - nextNeedsChange_ = false; - } - - // We have to decode it, let's setup the cache entry first. - entry->addr = texaddr; - entry->hash = texhash; - entry->dim = dim; - entry->format = format; - entry->maxLevel = maxLevel; - - // This would overestimate the size in many case so we underestimate instead - // to avoid excessive clearing caused by cache invalidations. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - - entry->cluthash = cluthash; - - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - - // Before we go reading the texture from memory, let's check for render-to-texture. - // We must do this early so we have the right w/h. - entry->framebuffer = 0; - for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { - auto framebuffer = fbCache_[i]; - AttachFramebuffer(entry, framebuffer->fb_address, framebuffer); - } - - // If we ended up with a framebuffer, attach it - no texture decoding needed. - if (entry->framebuffer) { - SetTextureFramebuffer(entry, entry->framebuffer); - } - - nextTexture_ = entry; - nextNeedsRehash_ = entry->framebuffer == nullptr; - // We still need to rebuild, to allocate a texture. But we'll bail early. - nextNeedsRebuild_= true; -} - bool TextureCacheGLES::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { bool replaceImages = false; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 9da5020017..a55c2a873c 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -46,8 +46,6 @@ public: TextureCacheGLES(Draw::DrawContext *draw); ~TextureCacheGLES(); - void SetTexture(bool force = false); - void Clear(bool delete_them); void StartFrame(); @@ -88,7 +86,7 @@ private: GLenum GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; void *DecodeTextureLevelOld(GETextureFormat format, GEPaletteFormat clutformat, int level, GLenum dstFmt, int scaleFactor, int *bufw = 0); TexCacheEntry::Status CheckAlpha(const u32 *pixelData, GLenum dstFmt, int stride, int w, int h); - void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); + void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index f276777263..8b3c067e94 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -303,10 +303,6 @@ void TextureCacheVulkan::EndFrame() { } } -static inline u32 MiniHash(const u32 *ptr) { - return ptr[0]; -} - void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutFormat == GE_CMODE_32BIT_ABGR8888 ? (clutBase * sizeof(u32)) : (clutBase * sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. @@ -488,218 +484,6 @@ VkFormat ToVulkanFormat(ReplacedTextureFormat fmt) { } } -void TextureCacheVulkan::SetTexture() { -#ifdef DEBUG_TEXTURES - if (SetDebugTexture()) { - // A different texture was bound, let's rebind next time. - lastBoundTexture = nullptr; - return; - } -#endif - - u8 level = 0; - if (IsFakeMipmapChange()) - level = (gstate.texlevel >> 20) & 0xF; - u32 texaddr = gstate.getTextureAddress(level); - if (!Memory::IsValidAddress(texaddr)) { - // Bind a null texture and return. - lastBoundTexture = nullptr; - return; - } - - const u16 dim = gstate.getTextureDimension(level); - int w = gstate.getTextureWidth(level); - int h = gstate.getTextureHeight(level); - if (texaddr == 0x04000000 && w == 2 && h == 2) { - // Nonsense bootup texture. Discard. - } - - GETextureFormat format = gstate.getTextureFormat(); - if (format >= 11) { - ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); - // TODO: Better assumption? - format = GE_TFMT_5650; - } - bool hasClut = gstate.isTextureFormatIndexed(); - - // Ignore uncached/kernel when caching. - u32 cluthash; - if (hasClut) { - if (clutLastFormat_ != gstate.clutformat) { - // We update here because the clut format can be specified after the load. - UpdateCurrentClut(gstate.getClutPaletteFormat(), gstate.getClutIndexStartPos(), gstate.isClutIndexSimple()); - } - cluthash = clutHash_ ^ gstate.clutformat; - } else { - cluthash = 0; - } - u64 cachekey = TexCacheEntry::CacheKey(texaddr, format, dim, cluthash); - - int bufw = GetTextureBufw(0, texaddr, format); - u8 maxLevel = gstate.getTextureMaxLevel(); - - u32 texhash = MiniHash((const u32 *)Memory::GetPointerUnchecked(texaddr)); - - TexCache::iterator iter = cache.find(cachekey); - TexCacheEntry *entry = NULL; - gstate_c.needShaderTexClamp = false; - gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; - - if (iter != cache.end()) { - entry = &iter->second; - // Validate the texture still matches the cache entry. - bool match = entry->Matches(dim, format, maxLevel); - const char *reason = "different params"; - - // Check for FBO - slow! - if (entry->framebuffer) { - if (match) { - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutAndTexRender, G3D, "Using rendered texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - SetTextureFramebuffer(entry, entry->framebuffer); - return; - } else { - // Make sure we re-evaluate framebuffers. - DetachFramebuffer(entry, texaddr, entry->framebuffer); - reason = "detached framebuf"; - match = false; - } - } - - bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE; - - // First let's see if another texture with the same address had a hashfail. - if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) { - // Always rehash in this case, if one changed the rest all probably did. - rehash = true; - entry->status &= ~TexCacheEntry::STATUS_CLUT_RECHECK; - } else if (!gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE)) { - // Okay, just some parameter change - the data didn't change, no need to rehash. - rehash = false; - } - - if (match) { - if (entry->lastFrame != gpuStats.numFlips) { - u32 diff = gpuStats.numFlips - entry->lastFrame; - entry->numFrames++; - - if (entry->framesUntilNextFullHash < diff) { - // Exponential backoff up to 512 frames. Textures are often reused. - if (entry->numFrames > 32) { - // Also, try to add some "randomness" to avoid rehashing several textures the same frame. - entry->framesUntilNextFullHash = std::min(512, entry->numFrames) + (entry->textureName & 15); - } else { - entry->framesUntilNextFullHash = entry->numFrames; - } - rehash = true; - } else { - entry->framesUntilNextFullHash -= diff; - } - } - - // If it's not huge or has been invalidated many times, recheck the whole texture. - if (entry->invalidHint > 180 || (entry->invalidHint > 15 && (dim >> 8) < 9 && (dim & 0xF) < 9)) { - entry->invalidHint = 0; - rehash = true; - } - - if (texhash != entry->hash) { - match = false; - } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - rehash = false; - } - } - - if (match && (entry->status & TexCacheEntry::STATUS_TO_SCALE) && standardScaleFactor_ != 1 && texelsScaledThisFrame_ < TEXCACHE_MAX_TEXELS_SCALED) { - if ((entry->status & TexCacheEntry::STATUS_CHANGE_FREQUENT) == 0) { - // INFO_LOG(G3D, "Reloading texture to do the scaling we skipped.."); - match = false; - reason = "scaling"; - } - } - - if (match) { - // TODO: Mark the entry reliable if it's been safe for long enough? - //got one! - if (entry->vkTex != lastBoundTexture) { - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - } - if (rehash) { - // Update in case any of these changed. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - entry->cluthash = cluthash; - } - - nextTexture_ = entry; - nextNeedsRehash_ = rehash; - nextNeedsChange_ = false; - // Might need a rebuild if the hash fails. - nextNeedsRebuild_= false; - VERBOSE_LOG(G3D, "Texture at %08x Found in Cache, applying", texaddr); - return; //Done! - } else { - nextChangeReason_ = reason; - nextNeedsChange_ = true; - } - } else { - VERBOSE_LOG(G3D, "No texture in cache, decoding..."); - TexCacheEntry entryNew = { 0 }; - cache[cachekey] = entryNew; - - if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { - WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); - } - - entry = &cache[cachekey]; - if (g_Config.bTextureBackoffCache) { - entry->status = TexCacheEntry::STATUS_HASHING; - } else { - entry->status = TexCacheEntry::STATUS_UNRELIABLE; - } - - nextNeedsChange_ = false; - } - - // We have to decode it, let's setup the cache entry first. - entry->addr = texaddr; - entry->hash = texhash; - entry->dim = dim; - entry->format = format; - entry->maxLevel = maxLevel; - - // This would overestimate the size in many case so we underestimate instead - // to avoid excessive clearing caused by cache invalidations. - entry->sizeInRAM = (textureBitsPerPixel[format] * bufw * h / 2) / 8; - entry->bufw = bufw; - - entry->cluthash = cluthash; - - gstate_c.curTextureWidth = w; - gstate_c.curTextureHeight = h; - - // Before we go reading the texture from memory, let's check for render-to-texture. - // We must do this early so we have the right w/h. - entry->framebuffer = 0; - for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { - auto framebuffer = fbCache_[i]; - AttachFramebuffer(entry, framebuffer->fb_address, framebuffer); - } - - // If we ended up with a framebuffer, attach it - no texture decoding needed. - if (entry->framebuffer) { - SetTextureFramebuffer(entry, entry->framebuffer); - } - - nextTexture_ = entry; - nextNeedsRehash_ = entry->framebuffer == nullptr; - // We still need to rebuild, to allocate a texture. But we'll bail early. - nextNeedsRebuild_= true; -} - bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 3041677b9f..ed49f55e59 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -67,7 +67,6 @@ public: TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan); ~TextureCacheVulkan(); - void SetTexture(); void StartFrame(); void EndFrame(); @@ -109,7 +108,7 @@ private: void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt); VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h); - void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple); + void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); From f753573332b9f54367acef20a059c707c2869d3d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:13:09 +0100 Subject: [PATCH 11/15] Unify HandleTextureChange --- GPU/Common/TextureCacheCommon.cpp | 37 +++++++++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 4 +-- GPU/D3D11/TextureCacheD3D11.cpp | 45 +++---------------------------- GPU/D3D11/TextureCacheD3D11.h | 3 +-- GPU/Directx9/TextureCacheDX9.cpp | 45 +++---------------------------- GPU/Directx9/TextureCacheDX9.h | 3 +-- GPU/GLES/TextureCacheGLES.cpp | 41 +--------------------------- GPU/GLES/TextureCacheGLES.h | 7 ++--- GPU/Vulkan/TextureCacheVulkan.cpp | 32 ---------------------- GPU/Vulkan/TextureCacheVulkan.h | 7 ++--- 10 files changed, 58 insertions(+), 166 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index fcac96f6a6..5bfcfd9c09 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -443,6 +443,43 @@ void TextureCacheCommon::DecimateVideos() { } } +bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { + bool replaceImages = false; + + cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry); + entry->numInvalidated++; + gpuStats.numTextureInvalidations++; + DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); + if (doDelete) { + if (initialMatch && standardScaleFactor_ == 1 && (entry->status & TexCacheEntry::STATUS_IS_SCALED) == 0) { + // Actually, if size and number of levels match, let's try to avoid deleting and recreating. + // Instead, let's use glTexSubImage to replace the images. + replaceImages = true; + } else { + InvalidateLastTexture(entry); + ReleaseTexture(entry); + entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; + } + } + // Clear the reliable bit if set. + if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { + entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); + } + + // Also, mark any textures with the same address but different clut. They need rechecking. + if (entry->cluthash != 0) { + const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; + const u64 cachekeyMax = cachekeyMin + (1ULL << 32); + for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { + if (it->second.cluthash != entry->cluthash) { + it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; + } + } + } + + return replaceImages; +} + void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg) { // Must be in VRAM so | 0x04000000 it is. Also, ignore memory mirrors. // These checks are mainly to reduce scanning all textures. diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 27fcbd9575..c42dd5b652 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -185,7 +185,7 @@ public: void ClearNextFrame(); virtual void ForgetLastTexture() = 0; - virtual void InvalidateLastTexture() = 0; + virtual void InvalidateLastTexture(TexCacheEntry *entry = nullptr) = 0; virtual void Clear(bool delete_them); // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. @@ -211,7 +211,7 @@ protected: void Decimate(); virtual void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) = 0; - virtual bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) = 0; + bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); virtual void BuildTexture(TexCacheEntry *const entry, bool replaceImages) = 0; virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0; bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 25f6dadd4c..3947a0734d 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -140,8 +140,10 @@ void TextureCacheD3D11::ForgetLastTexture() { context_->PSSetShaderResources(0, 1, &nullTex); } -void TextureCacheD3D11::InvalidateLastTexture() { - lastBoundTexture = INVALID_TEX; +void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) { + if (!entry || entry->texturePtr == lastBoundTexture) { + lastBoundTexture = INVALID_TEX; + } } DXGI_FORMAT getClutDestFormatD3D11(GEPaletteFormat format) { @@ -507,45 +509,6 @@ bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete return true; } -bool TextureCacheD3D11::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { - bool replaceImages = false; - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry); - entry->numInvalidated++; - gpuStats.numTextureInvalidations++; - DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); - if (doDelete) { - if (initialMatch && standardScaleFactor_ == 1 && (entry->status & TexCacheEntry::STATUS_IS_SCALED) == 0) { - // Actually, if size and number of levels match, let's try to avoid deleting and recreating. - // Instead, let's use glTexSubImage to replace the images. - replaceImages = true; - } else { - if (entry->texturePtr == lastBoundTexture) { - lastBoundTexture = INVALID_TEX; - } - ReleaseTexture(entry); - entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; - } - } - // Clear the reliable bit if set. - if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - } - - // Also, mark any textures with the same address but different clut. They need rechecking. - if (entry->cluthash != 0) { - const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; - const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second.cluthash != entry->cluthash) { - it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; - } - } - } - - return replaceImages; -} - void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 4f1c4aa6a9..a8e0d895e8 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -60,7 +60,7 @@ public: bool DecodeTexture(u8 *output, const GPUgstate &state); void ForgetLastTexture() override; - void InvalidateLastTexture() override; + void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); @@ -79,7 +79,6 @@ private: bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; ID3D11Device *device_; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 57da0cda9b..bbff0f43a0 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -108,8 +108,10 @@ void TextureCacheDX9::ForgetLastTexture() { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } -void TextureCacheDX9::InvalidateLastTexture() { - lastBoundTexture = INVALID_TEX; +void TextureCacheDX9::InvalidateLastTexture(TexCacheEntry *entry) { + if (!entry || entry->texturePtr == lastBoundTexture) { + lastBoundTexture = INVALID_TEX; + } } D3DFORMAT getClutDestFormat(GEPaletteFormat format) { @@ -527,45 +529,6 @@ bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) return true; } -bool TextureCacheDX9::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { - bool replaceImages = false; - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry); - entry->numInvalidated++; - gpuStats.numTextureInvalidations++; - DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); - if (doDelete) { - if (initialMatch && standardScaleFactor_ == 1 && (entry->status & TexCacheEntry::STATUS_IS_SCALED) == 0) { - // Actually, if size and number of levels match, let's try to avoid deleting and recreating. - // Instead, let's use glTexSubImage to replace the images. - replaceImages = true; - } else { - if (entry->texturePtr == lastBoundTexture) { - lastBoundTexture = INVALID_TEX; - } - ReleaseTexture(entry); - entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; - } - } - // Clear the reliable bit if set. - if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - } - - // Also, mark any textures with the same address but different clut. They need rechecking. - if (entry->cluthash != 0) { - const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; - const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second.cluthash != entry->cluthash) { - it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; - } - } - } - - return replaceImages; -} - void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 7e5f88a076..94cbf3d1f1 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -54,7 +54,7 @@ public: bool DecodeTexture(u8 *output, const GPUgstate &state); void ForgetLastTexture() override; - void InvalidateLastTexture() override; + void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); @@ -73,7 +73,6 @@ private: bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; LPDIRECT3DTEXTURE9 &DxTex(TexCacheEntry *entry) { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index dd2c1bec6b..c905869701 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -221,7 +221,7 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, GLuint dstFmt, int n } void TextureCacheGLES::StartFrame() { - lastBoundTexture = INVALID_TEX; + InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; if (texelsScaledThisFrame_) { @@ -531,45 +531,6 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) { } } -bool TextureCacheGLES::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { - bool replaceImages = false; - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry); - entry->numInvalidated++; - gpuStats.numTextureInvalidations++; - DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); - if (doDelete) { - if (initialMatch && standardScaleFactor_ == 1 && (entry->status & TexCacheEntry::STATUS_IS_SCALED) == 0) { - // Actually, if size and number of levels match, let's try to avoid deleting and recreating. - // Instead, let's use glTexSubImage to replace the images. - replaceImages = true; - } else { - if (entry->textureName == lastBoundTexture) { - lastBoundTexture = INVALID_TEX; - } - ReleaseTexture(entry); - entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; - } - } - // Clear the reliable bit if set. - if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - } - - // Also, mark any textures with the same address but different clut. They need rechecking. - if (entry->cluthash != 0) { - const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; - const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second.cluthash != entry->cluthash) { - it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; - } - } - } - - return replaceImages; -} - void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index a55c2a873c..6b41125420 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -64,8 +64,10 @@ public: lastBoundTexture = INVALID_TEX; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } - void InvalidateLastTexture() override { - lastBoundTexture = INVALID_TEX; + void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override { + if (!entry || entry->textureName == lastBoundTexture) { + lastBoundTexture = INVALID_TEX; + } } u32 AllocTextureName(); @@ -89,7 +91,6 @@ private: void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; std::vector nameCache_; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 8b3c067e94..65546840e6 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -547,38 +547,6 @@ bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelet return true; } -bool TextureCacheVulkan::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { - cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry); - entry->numInvalidated++; - gpuStats.numTextureInvalidations++; - DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); - if (doDelete) { - if (entry->vkTex == lastBoundTexture) { - lastBoundTexture = nullptr; - } - delete entry->vkTex; - entry->vkTex = nullptr; - entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; - } - // Clear the reliable bit if set. - if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - } - - // Also, mark any textures with the same address but different clut. They need rechecking. - if (entry->cluthash != 0) { - const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; - const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second.cluthash != entry->cluthash) { - it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; - } - } - } - - return false; -} - void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index ed49f55e59..4d3d709f37 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -88,8 +88,10 @@ public: lastBoundTexture = nullptr; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } - void InvalidateLastTexture() override { - lastBoundTexture = nullptr; + void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override { + if (!entry || entry->vkTex == lastBoundTexture) { + lastBoundTexture = nullptr; + } } void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { @@ -113,7 +115,6 @@ private: bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; - bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; VulkanContext *vulkan_; From 4652c6af284d81ec1fc8a90159bd251aab919dc6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:19:58 +0100 Subject: [PATCH 12/15] Some member variable renaming to match the convention --- GPU/Common/TextureCacheCommon.cpp | 88 +++++++++++++++---------------- GPU/Common/TextureCacheCommon.h | 14 ++--- GPU/D3D11/TextureCacheD3D11.cpp | 20 +++---- GPU/Directx9/TextureCacheDX9.cpp | 22 ++++---- GPU/GLES/TextureCacheGLES.cpp | 20 +++---- GPU/Vulkan/TextureCacheVulkan.cpp | 24 ++++----- 6 files changed, 94 insertions(+), 94 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5bfcfd9c09..c272e7e5c8 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -75,11 +75,11 @@ TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw) clutBuf_ = clutBufConverted_; // These buffers will grow if necessary, but most won't need more than this. - tmpTexBuf32.resize(512 * 512); // 1MB - tmpTexBuf16.resize(512 * 512); // 0.5MB - tmpTexBufRearrange.resize(512 * 512); // 1MB + tmpTexBuf32_.resize(512 * 512); // 1MB + tmpTexBuf16_.resize(512 * 512); // 0.5MB + tmpTexBufRearrange_.resize(512 * 512); // 1MB - replacer.Init(); + replacer_.Init(); } TextureCacheCommon::~TextureCacheCommon() { @@ -228,13 +228,13 @@ void TextureCacheCommon::SetTexture(bool force) { u32 texhash = MiniHash((const u32 *)Memory::GetPointerUnchecked(texaddr)); - TexCache::iterator iter = cache.find(cachekey); + TexCache::iterator iter = cache_.find(cachekey); TexCacheEntry *entry = NULL; gstate_c.needShaderTexClamp = false; gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; gstate_c.bgraTexture = isBgraBackend_; - if (iter != cache.end()) { + if (iter != cache_.end()) { entry = &iter->second; // Validate the texture still matches the cache entry. bool match = entry->Matches(dim, format, maxLevel); @@ -335,13 +335,13 @@ void TextureCacheCommon::SetTexture(bool force) { } else { VERBOSE_LOG(G3D, "No texture in cache, decoding..."); TexCacheEntry entryNew = { 0 }; - cache[cachekey] = entryNew; + cache_[cachekey] = entryNew; if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); } - entry = &cache[cachekey]; + entry = &cache_[cachekey]; if (g_Config.bTextureBackoffCache) { entry->status = TexCacheEntry::STATUS_HASHING; } else { @@ -400,7 +400,7 @@ void TextureCacheCommon::Decimate() { ForgetLastTexture(); int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { + for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ) { if (iter->second.lastFrame + killAge < gpuStats.numFlips) { DeleteTexture(iter++); } else { @@ -414,12 +414,12 @@ void TextureCacheCommon::Decimate() { if (g_Config.bTextureSecondaryCache && secondCacheSizeEstimate_ >= TEXCACHE_SECOND_MIN_PRESSURE) { const u32 had = secondCacheSizeEstimate_; - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ) { + for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ) { // In low memory mode, we kill them all. if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { ReleaseTexture(&iter->second); secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(&iter->second); - secondCache.erase(iter++); + secondCache_.erase(iter++); } else { ++iter; } @@ -470,7 +470,7 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c if (entry->cluthash != 0) { const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; const u64 cachekeyMax = cachekeyMin + (1ULL << 32); - for (auto it = cache.lower_bound(cachekeyMin), end = cache.upper_bound(cachekeyMax); it != end; ++it) { + for (auto it = cache_.lower_bound(cachekeyMin), end = cache_.upper_bound(cachekeyMax); it != end; ++it) { if (it->second.cluthash != entry->cluthash) { it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; } @@ -501,11 +501,11 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram if (std::find(fbCache_.begin(), fbCache_.end(), framebuffer) == fbCache_.end()) { fbCache_.push_back(framebuffer); } - for (auto it = cache.lower_bound(cacheKey), end = cache.upper_bound(cacheKeyEnd); it != end; ++it) { + for (auto it = cache_.lower_bound(cacheKey), end = cache_.upper_bound(cacheKeyEnd); it != end; ++it) { AttachFramebuffer(&it->second, addr, framebuffer); } // Let's assume anything in mirrors is fair game to check. - for (auto it = cache.lower_bound(mirrorCacheKey), end = cache.upper_bound(mirrorCacheKeyEnd); it != end; ++it) { + for (auto it = cache_.lower_bound(mirrorCacheKey), end = cache_.upper_bound(mirrorCacheKeyEnd); it != end; ++it) { const u64 mirrorlessKey = it->first & ~0x0060000000000000ULL; // Let's still make sure it's in the cache range. if (mirrorlessKey >= cacheKey && mirrorlessKey <= cacheKeyEnd) { @@ -524,7 +524,7 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram // We might erase, so move to the next one already (which won't become invalid.) ++it; - DetachFramebuffer(&cache[cachekey], addr, framebuffer); + DetachFramebuffer(&cache_[cachekey], addr, framebuffer); } break; } @@ -742,8 +742,8 @@ bool TextureCacheCommon::SetOffsetTexture(u32 offset) { const u16 dim = gstate.getTextureDimension(0); u64 cachekey = TexCacheEntry::CacheKey(texaddr, gstate.getTextureFormat(), dim, 0); - TexCache::iterator iter = cache.find(cachekey); - if (iter == cache.end()) { + TexCache::iterator iter = cache_.find(cachekey); + if (iter == cache_.end()) { return false; } TexCacheEntry *entry = &iter->second; @@ -804,7 +804,7 @@ void TextureCacheCommon::NotifyConfigChanged() { standardScaleFactor_ = scaleFactor; - replacer.NotifyConfigChanged(); + replacer_.NotifyConfigChanged(); } void TextureCacheCommon::NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt) { @@ -995,9 +995,9 @@ bool TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm const int clutSharingOffset = mipmapShareClut ? 0 : level * 16; if (swizzled) { - tmpTexBuf32.resize(bufw * ((h + 7) & ~7)); - UnswizzleFromMem(tmpTexBuf32.data(), bufw / 2, texptr, bufw, h, 0); - texptr = (u8 *)tmpTexBuf32.data(); + tmpTexBuf32_.resize(bufw * ((h + 7) & ~7)); + UnswizzleFromMem(tmpTexBuf32_.data(), bufw / 2, texptr, bufw, h, 0); + texptr = (u8 *)tmpTexBuf32_.data(); } switch (clutformat) { @@ -1080,9 +1080,9 @@ bool TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm } } else { // We don't have enough space for all rows in out, so use a temp buffer. - tmpTexBuf32.resize(bufw * ((h + 7) & ~7)); - UnswizzleFromMem(tmpTexBuf32.data(), bufw * 2, texptr, bufw, h, 2); - const u8 *unswizzled = (u8 *)tmpTexBuf32.data(); + tmpTexBuf32_.resize(bufw * ((h + 7) & ~7)); + UnswizzleFromMem(tmpTexBuf32_.data(), bufw * 2, texptr, bufw, h, 2); + const u8 *unswizzled = (u8 *)tmpTexBuf32_.data(); if (reverseColors) { for (int y = 0; y < h; ++y) { @@ -1114,9 +1114,9 @@ bool TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm } } else { // We don't have enough space for all rows in out, so use a temp buffer. - tmpTexBuf32.resize(bufw * ((h + 7) & ~7)); - UnswizzleFromMem(tmpTexBuf32.data(), bufw * 4, texptr, bufw, h, 4); - const u8 *unswizzled = (u8 *)tmpTexBuf32.data(); + tmpTexBuf32_.resize(bufw * ((h + 7) & ~7)); + UnswizzleFromMem(tmpTexBuf32_.data(), bufw * 4, texptr, bufw, h, 4); + const u8 *unswizzled = (u8 *)tmpTexBuf32_.data(); if (reverseColors) { for (int y = 0; y < h; ++y) { @@ -1209,9 +1209,9 @@ bool TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const int h = gstate.getTextureHeight(level); if (gstate.isTextureSwizzled()) { - tmpTexBuf32.resize(bufw * ((h + 7) & ~7)); - UnswizzleFromMem(tmpTexBuf32.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex); - texptr = (u8 *)tmpTexBuf32.data(); + tmpTexBuf32_.resize(bufw * ((h + 7) & ~7)); + UnswizzleFromMem(tmpTexBuf32_.data(), bufw * bytesPerIndex, texptr, bufw, h, bytesPerIndex); + texptr = (u8 *)tmpTexBuf32_.data(); } switch (gstate.getClutPaletteFormat()) { @@ -1291,7 +1291,7 @@ void TextureCacheCommon::ApplyTexture() { // Update the hash on the texture. int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); } if (nextNeedsChange_) { // This texture existed previously, let's handle the change. @@ -1330,17 +1330,17 @@ void TextureCacheCommon::ApplyTexture() { void TextureCacheCommon::Clear(bool delete_them) { ForgetLastTexture(); if (delete_them) { - for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { + for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { ReleaseTexture(&iter->second); } - for (TexCache::iterator iter = secondCache.begin(); iter != secondCache.end(); ++iter) { + for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ++iter) { ReleaseTexture(&iter->second); } } - if (cache.size() + secondCache.size()) { - INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache.size() + secondCache.size())); - cache.clear(); - secondCache.clear(); + if (cache_.size() + secondCache_.size()) { + INFO_LOG(G3D, "Texture cached cleared from %i textures", (int)(cache_.size() + secondCache_.size())); + cache_.clear(); + secondCache_.clear(); cacheSizeEstimate_ = 0; secondCacheSizeEstimate_ = 0; } @@ -1355,14 +1355,14 @@ void TextureCacheCommon::DeleteTexture(TexCache::iterator it) { fbTexInfo_.erase(fbInfo); } cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache.erase(it); + cache_.erase(it); } bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); if (fullhash != entry->fullhash) { hashFail = true; } else { @@ -1393,8 +1393,8 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelet if (g_Config.bTextureSecondaryCache) { if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache.find(secondKey); - if (secondIter != secondCache.end()) { + TexCache::iterator secondIter = secondCache_.find(secondKey); + if (secondIter != secondCache_.end()) { TexCacheEntry *secondEntry = &secondIter->second; if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { // Reset the numInvalidated value lower, we got a match. @@ -1407,7 +1407,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelet } else { secondKey = entry->fullhash | ((u64)entry->cluthash << 32); secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache[secondKey] = *entry; + secondCache_[secondKey] = *entry; doDelete = false; } } @@ -1438,7 +1438,7 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type endKey = (u64)-1; } - for (TexCache::iterator iter = cache.lower_bound(startKey), end = cache.upper_bound(endKey); iter != end; ++iter) { + for (TexCache::iterator iter = cache_.lower_bound(startKey), end = cache_.upper_bound(endKey); iter != end; ++iter) { u32 texAddr = iter->second.addr; u32 texEnd = iter->second.addr + iter->second.sizeInRAM; @@ -1476,7 +1476,7 @@ void TextureCacheCommon::InvalidateAll(GPUInvalidationType /*unused*/) { } timesInvalidatedAllThisFrame_++; - for (TexCache::iterator iter = cache.begin(), end = cache.end(); iter != end; ++iter) { + for (TexCache::iterator iter = cache_.begin(), end = cache_.end(); iter != end; ++iter) { if (iter->second.GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { iter->second.SetHashStatus(TexCacheEntry::STATUS_HASHING); } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index c42dd5b652..40e21bdea5 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -196,7 +196,7 @@ public: int AttachedDrawingHeight(); size_t NumLoadedTextures() const { - return cache.size(); + return cache_.size(); } bool IsFakeMipmapChange() { @@ -268,7 +268,7 @@ protected: } Draw::DrawContext *draw_; - TextureReplacer replacer; + TextureReplacer replacer_; FramebufferManagerCommon *framebufferManager_; bool clearCacheNextFrame_; @@ -278,10 +278,10 @@ protected: int texelsScaledThisFrame_; int timesInvalidatedAllThisFrame_; - TexCache cache; + TexCache cache_; u32 cacheSizeEstimate_; - TexCache secondCache; + TexCache secondCache_; u32 secondCacheSizeEstimate_; std::vector fbCache_; @@ -289,9 +289,9 @@ protected: std::map videos_; - SimpleBuf tmpTexBuf32; - SimpleBuf tmpTexBuf16; - SimpleBuf tmpTexBufRearrange; + SimpleBuf tmpTexBuf32_; + SimpleBuf tmpTexBuf16_; + SimpleBuf tmpTexBufRearrange_; TexCacheEntry *nextTexture_; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 3947a0734d..d249a31d1f 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -450,7 +450,7 @@ bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete bool hashFail = false; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); if (fullhash != entry->fullhash) { hashFail = true; } else { @@ -481,8 +481,8 @@ bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete if (g_Config.bTextureSecondaryCache) { if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache.find(secondKey); - if (secondIter != secondCache.end()) { + TexCache::iterator secondIter = secondCache_.find(secondKey); + if (secondIter != secondCache_.end()) { TexCacheEntry *secondEntry = &secondIter->second; if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { // Reset the numInvalidated value lower, we got a match. @@ -495,7 +495,7 @@ bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete } else { secondKey = entry->fullhash | ((u64)entry->cluthash << 32); secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache[secondKey] = *entry; + secondCache_[secondKey] = *entry; doDelete = false; } } @@ -566,10 +566,10 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma scaleFactor = scaleFactor > 4 ? 4 : (scaleFactor > 2 ? 2 : 1); } - u64 cachekey = replacer.Enabled() ? entry->CacheKey() : 0; + u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - ReplacedTexture &replaced = replacer.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. @@ -757,8 +757,8 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & u32 *pixelData; int decPitch; if (scaleFactor > 1) { - tmpTexBufRearrange.resize(std::max(bufw, w) * h); - pixelData = tmpTexBufRearrange.data(); + tmpTexBufRearrange_.resize(std::max(bufw, w) * h); + pixelData = tmpTexBufRearrange_.data(); // We want to end up with a neatly packed texture for scaling. decPitch = w * bpp; mapData = new u32[(w * scaleFactor) * (h * scaleFactor)]; @@ -802,7 +802,7 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN); } - if (replacer.Enabled()) { + if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; replacedInfo.cachekey = entry.CacheKey(); replacedInfo.hash = entry.fullhash; @@ -812,7 +812,7 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture & replacedInfo.scaleFactor = scaleFactor; replacedInfo.fmt = FromD3D11Format(dstFmt); - replacer.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h); } } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index bbff0f43a0..2deb7d56b7 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -100,7 +100,7 @@ void TextureCacheDX9::DeleteTexture(TexCache::iterator it) { fbTexInfo_.erase(fbInfo); } cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache.erase(it); + cache_.erase(it); } void TextureCacheDX9::ForgetLastTexture() { @@ -470,7 +470,7 @@ bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) bool hashFail = false; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); if (fullhash != entry->fullhash) { hashFail = true; } else { @@ -501,8 +501,8 @@ bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) if (g_Config.bTextureSecondaryCache) { if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache.find(secondKey); - if (secondIter != secondCache.end()) { + TexCache::iterator secondIter = secondCache_.find(secondKey); + if (secondIter != secondCache_.end()) { TexCacheEntry *secondEntry = &secondIter->second; if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { // Reset the numInvalidated value lower, we got a match. @@ -515,7 +515,7 @@ bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) } else { secondKey = entry->fullhash | ((u64)entry->cluthash << 32); secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache[secondKey] = *entry; + secondCache_[secondKey] = *entry; doDelete = false; } } @@ -586,10 +586,10 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage scaleFactor = scaleFactor > 4 ? 4 : (scaleFactor > 2 ? 2 : 1); } - u64 cachekey = replacer.Enabled() ? entry->CacheKey() : 0; + u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - ReplacedTexture &replaced = replacer.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. @@ -774,8 +774,8 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re u32 *pixelData = (u32 *)rect.pBits; int decPitch = rect.Pitch; if (scaleFactor > 1) { - tmpTexBufRearrange.resize(std::max(bufw, w) * h); - pixelData = tmpTexBufRearrange.data(); + tmpTexBufRearrange_.resize(std::max(bufw, w) * h); + pixelData = tmpTexBufRearrange_.data(); // We want to end up with a neatly packed texture for scaling. decPitch = w * bpp; } @@ -811,7 +811,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN); } - if (replacer.Enabled()) { + if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; replacedInfo.cachekey = entry.CacheKey(); replacedInfo.hash = entry.fullhash; @@ -821,7 +821,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re replacedInfo.scaleFactor = scaleFactor; replacedInfo.fmt = FromD3D9Format(dstFmt); - replacer.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h); } } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index c905869701..506a341e29 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -590,10 +590,10 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag scaleFactor = scaleFactor > 4 ? 4 : (scaleFactor > 2 ? 2 : 1); } - u64 cachekey = replacer.Enabled() ? entry->CacheKey() : 0; + u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - ReplacedTexture &replaced = replacer.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); if (replaced.GetSize(0, w, h)) { if (replaceImages) { // Since we're replacing the texture, we can't replace the image inside. @@ -764,9 +764,9 @@ void *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteF decPitch = bufw * pixelSize; } - tmpTexBufRearrange.resize(std::max(w, bufw) * h); - if (DecodeTextureLevel((u8 *)tmpTexBufRearrange.data(), decPitch, format, clutformat, texaddr, level, bufw, true, UseBGRA8888())) { - finalBuf = tmpTexBufRearrange.data(); + tmpTexBufRearrange_.resize(std::max(w, bufw) * h); + if (DecodeTextureLevel((u8 *)tmpTexBufRearrange_.data(), decPitch, format, clutformat, texaddr, level, bufw, true, UseBGRA8888())) { + finalBuf = tmpTexBufRearrange_.data(); } else { finalBuf = nullptr; } @@ -814,10 +814,10 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r if (replaced.GetSize(level, w, h)) { PROFILE_THIS_SCOPE("replacetex"); - tmpTexBufRearrange.resize(w * h); + tmpTexBufRearrange_.resize(w * h); int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2; - replaced.Load(level, tmpTexBufRearrange.data(), bpp * w); - pixelData = tmpTexBufRearrange.data(); + replaced.Load(level, tmpTexBufRearrange_.data(), bpp * w); + pixelData = tmpTexBufRearrange_.data(); dstFmt = ToGLESFormat(replaced.Format(level)); @@ -854,7 +854,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN); } - if (replacer.Enabled()) { + if (replacer_.Enabled()) { ReplacedTextureDecodeInfo replacedInfo; replacedInfo.cachekey = entry.CacheKey(); replacedInfo.hash = entry.fullhash; @@ -865,7 +865,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r replacedInfo.fmt = FromGLESFormat(dstFmt, useBGRA); int bpp = dstFmt == GL_UNSIGNED_BYTE ? 4 : 2; - replacer.NotifyTextureDecoded(replacedInfo, pixelData, (useUnpack ? bufw : w) * bpp, level, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, pixelData, (useUnpack ? bufw : w) * bpp, level, w, h); } } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 65546840e6..be3fdd135f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -192,7 +192,7 @@ void TextureCacheVulkan::DeleteTexture(TexCache::iterator it) { } cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache.erase(it); + cache_.erase(it); } VkFormat getClutDestFormatVulkan(GEPaletteFormat format) { @@ -488,7 +488,7 @@ bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelet bool hashFail = false; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); if (fullhash != entry->fullhash) { hashFail = true; } else { @@ -519,8 +519,8 @@ bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelet if (g_Config.bTextureSecondaryCache) { if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache.find(secondKey); - if (secondIter != secondCache.end()) { + TexCache::iterator secondIter = secondCache_.find(secondKey); + if (secondIter != secondCache_.end()) { TexCacheEntry *secondEntry = &secondIter->second; if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { // Reset the numInvalidated value lower, we got a match. @@ -533,7 +533,7 @@ bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelet } else { secondKey = entry->fullhash | ((u64)entry->cluthash << 32); secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache[secondKey] = *entry; + secondCache_[secondKey] = *entry; doDelete = false; } } @@ -601,10 +601,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm scaleFactor = scaleFactor > 4 ? 4 : (scaleFactor > 2 ? 2 : 1); } - u64 cachekey = replacer.Enabled() ? entry->CacheKey() : 0; + u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - ReplacedTexture &replaced = replacer.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); if (replaced.GetSize(0, w, h)) { // We're replacing, so we won't scale. scaleFactor = 1; @@ -700,7 +700,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm lastBoundTexture = entry->vkTex; ReplacedTextureDecodeInfo replacedInfo; - if (replacer.Enabled() && !replaced.Valid()) { + if (replacer_.Enabled() && !replaced.Valid()) { replacedInfo.cachekey = cachekey; replacedInfo.hash = entry->fullhash; replacedInfo.addr = entry->addr; @@ -735,8 +735,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceIm break; } else LoadTextureLevel(*entry, (uint8_t *)data, stride, i, scaleFactor, dstFmt); - if (replacer.Enabled()) { - replacer.NotifyTextureDecoded(replacedInfo, data, stride, i, mipWidth, mipHeight); + if (replacer_.Enabled()) { + replacer_.NotifyTextureDecoded(replacedInfo, data, stride, i, mipWidth, mipHeight); } } entry->vkTex->texture_->UploadMip(i, mipWidth, mipHeight, texBuf, bufferOffset, stride / bpp); @@ -813,8 +813,8 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt u32 *pixelData = (u32 *)writePtr; int decPitch = rowPitch; if (scaleFactor > 1) { - tmpTexBufRearrange.resize(std::max(bufw, w) * h); - pixelData = tmpTexBufRearrange.data(); + tmpTexBufRearrange_.resize(std::max(bufw, w) * h); + pixelData = tmpTexBufRearrange_.data(); // We want to end up with a neatly packed texture for scaling. decPitch = w * bpp; } From 4c897ff853dd89f9ca270f5c88f76e38de5f7ec4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:21:54 +0100 Subject: [PATCH 13/15] Forgot to delete CheckFullHash duplicates --- GPU/D3D11/TextureCacheD3D11.cpp | 62 ------------------------------ GPU/D3D11/TextureCacheD3D11.h | 2 - GPU/Directx9/TextureCacheDX9.cpp | 63 ------------------------------- GPU/Directx9/TextureCacheDX9.h | 1 - GPU/Vulkan/TextureCacheVulkan.cpp | 63 ------------------------------- GPU/Vulkan/TextureCacheVulkan.h | 1 - 6 files changed, 192 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d249a31d1f..4fe76f1433 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -446,68 +446,6 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra lastBoundTexture = INVALID_TEX; } -bool TextureCacheD3D11::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { - bool hashFail = false; - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - if (fullhash != entry->fullhash) { - hashFail = true; - } else { - if (g_Config.bTextureBackoffCache) { - if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) { - // Reset to STATUS_HASHING. - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) { - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - - if (hashFail) { - entry->status |= TexCacheEntry::STATUS_UNRELIABLE; - if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) { - if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) { - entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE; - } else { - entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - entry->numFrames = 0; - - // Don't give up just yet. Let's try the secondary cache if it's been invalidated before. - // If it's failed a bunch of times, then the second cache is just wasting time and VRAM. - if (g_Config.bTextureSecondaryCache) { - if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { - u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache_.find(secondKey); - if (secondIter != secondCache_.end()) { - TexCacheEntry *secondEntry = &secondIter->second; - if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { - // Reset the numInvalidated value lower, we got a match. - if (entry->numInvalidated > 8) { - --entry->numInvalidated; - } - nextTexture_ = secondEntry; - return true; - } - } else { - secondKey = entry->fullhash | ((u64)entry->cluthash << 32); - secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache_[secondKey] = *entry; - doDelete = false; - } - } - } - - // We know it failed, so update the full hash right away. - entry->fullhash = fullhash; - return false; - } - - return true; -} void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index a8e0d895e8..68b2156f1f 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -76,8 +76,6 @@ private: TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; - bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); - void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 2deb7d56b7..5d38233e2b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -466,69 +466,6 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame lastBoundTexture = INVALID_TEX; } -bool TextureCacheDX9::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { - bool hashFail = false; - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - if (fullhash != entry->fullhash) { - hashFail = true; - } else { - if (g_Config.bTextureBackoffCache) { - if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) { - // Reset to STATUS_HASHING. - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) { - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - - if (hashFail) { - entry->status |= TexCacheEntry::STATUS_UNRELIABLE; - if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) { - if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) { - entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE; - } else { - entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - entry->numFrames = 0; - - // Don't give up just yet. Let's try the secondary cache if it's been invalidated before. - // If it's failed a bunch of times, then the second cache is just wasting time and VRAM. - if (g_Config.bTextureSecondaryCache) { - if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { - u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache_.find(secondKey); - if (secondIter != secondCache_.end()) { - TexCacheEntry *secondEntry = &secondIter->second; - if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { - // Reset the numInvalidated value lower, we got a match. - if (entry->numInvalidated > 8) { - --entry->numInvalidated; - } - nextTexture_ = secondEntry; - return true; - } - } else { - secondKey = entry->fullhash | ((u64)entry->cluthash << 32); - secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache_[secondKey] = *entry; - doDelete = false; - } - } - } - - // We know it failed, so update the full hash right away. - entry->fullhash = fullhash; - return false; - } - - return true; -} - void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 94cbf3d1f1..468b51ca1c 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -71,7 +71,6 @@ private: TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; - bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index be3fdd135f..d42cb45bda 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -484,69 +484,6 @@ VkFormat ToVulkanFormat(ReplacedTextureFormat fmt) { } } -bool TextureCacheVulkan::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { - bool hashFail = false; - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - u32 fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); - if (fullhash != entry->fullhash) { - hashFail = true; - } else { - if (g_Config.bTextureBackoffCache) { - if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) { - // Reset to STATUS_HASHING. - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) { - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - - if (hashFail) { - entry->status |= TexCacheEntry::STATUS_UNRELIABLE; - if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) { - if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) { - entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE; - } else { - entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - entry->numFrames = 0; - - // Don't give up just yet. Let's try the secondary cache if it's been invalidated before. - // If it's failed a bunch of times, then the second cache is just wasting time and VRAM. - if (g_Config.bTextureSecondaryCache) { - if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { - u64 secondKey = fullhash | (u64)entry->cluthash << 32; - TexCache::iterator secondIter = secondCache_.find(secondKey); - if (secondIter != secondCache_.end()) { - TexCacheEntry *secondEntry = &secondIter->second; - if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { - // Reset the numInvalidated value lower, we got a match. - if (entry->numInvalidated > 8) { - --entry->numInvalidated; - } - nextTexture_ = secondEntry; - return true; - } - } else { - secondKey = entry->fullhash | ((u64)entry->cluthash << 32); - secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache_[secondKey] = *entry; - doDelete = false; - } - } - } - - // We know it failed, so update the full hash right away. - entry->fullhash = fullhash; - return false; - } - - return true; -} - void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, bool replaceImages) { entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 4d3d709f37..5b00b8472c 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -113,7 +113,6 @@ private: void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); - bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; From ca9050af12c9e8571a0186b0b922bc264be06d44 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:36:37 +0100 Subject: [PATCH 14/15] These should be deleted too. --- GPU/Directx9/TextureCacheDX9.cpp | 10 ---------- GPU/Directx9/TextureCacheDX9.h | 1 - GPU/Vulkan/TextureCacheVulkan.cpp | 11 ----------- GPU/Vulkan/TextureCacheVulkan.h | 3 +-- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 5d38233e2b..ed956e6429 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -93,16 +93,6 @@ void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry) { } } -void TextureCacheDX9::DeleteTexture(TexCache::iterator it) { - ReleaseTexture(&it->second); - auto fbInfo = fbTexInfo_.find(it->first); - if (fbInfo != fbTexInfo_.end()) { - fbTexInfo_.erase(fbInfo); - } - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache_.erase(it); -} - void TextureCacheDX9::ForgetLastTexture() { lastBoundTexture = INVALID_TEX; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 468b51ca1c..714b467315 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -64,7 +64,6 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, bool force); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt); D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index d42cb45bda..3272a06e56 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -184,17 +184,6 @@ void TextureCacheVulkan::ReleaseTexture(TexCacheEntry *entry) { delete entry->vkTex; } -void TextureCacheVulkan::DeleteTexture(TexCache::iterator it) { - delete it->second.vkTex; - auto fbInfo = fbTexInfo_.find(it->first); - if (fbInfo != fbTexInfo_.end()) { - fbTexInfo_.erase(fbInfo); - } - - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); - cache_.erase(it); -} - VkFormat getClutDestFormatVulkan(GEPaletteFormat format) { switch (format) { case GE_CMODE_16BIT_ABGR4444: diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 5b00b8472c..d720b20be3 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -98,6 +98,7 @@ public: imageView = imageView_; sampler = sampler_; } + void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); protected: void BindTexture(TexCacheEntry *entry) override; @@ -105,13 +106,11 @@ protected: void ReleaseTexture(TexCacheEntry *entry) override; private: - void DeleteTexture(TexCache::iterator it); void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key); void LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePtr, int rowPitch, int level, int scaleFactor, VkFormat dstFmt); VkFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::Status CheckAlpha(const u32 *pixelData, VkFormat dstFmt, int stride, int w, int h); void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override; - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer) override; void BuildTexture(TexCacheEntry *const entry, bool replaceImages) override; From 195eb94c8ea6cd5a0d81d06aead9cd09fe402a1d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Feb 2017 00:45:07 +0100 Subject: [PATCH 15/15] Texcache: Keep pointers to entries instead of full entries in the map. --- GPU/Common/TextureCacheCommon.cpp | 73 ++++++++++++++++--------------- GPU/Common/TextureCacheCommon.h | 5 ++- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c272e7e5c8..505b928500 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -229,13 +229,13 @@ void TextureCacheCommon::SetTexture(bool force) { u32 texhash = MiniHash((const u32 *)Memory::GetPointerUnchecked(texaddr)); TexCache::iterator iter = cache_.find(cachekey); - TexCacheEntry *entry = NULL; + TexCacheEntry *entry = nullptr; gstate_c.needShaderTexClamp = false; gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; gstate_c.bgraTexture = isBgraBackend_; if (iter != cache_.end()) { - entry = &iter->second; + entry = iter->second.get(); // Validate the texture still matches the cache entry. bool match = entry->Matches(dim, format, maxLevel); const char *reason = "different params"; @@ -334,14 +334,14 @@ void TextureCacheCommon::SetTexture(bool force) { } } else { VERBOSE_LOG(G3D, "No texture in cache, decoding..."); - TexCacheEntry entryNew = { 0 }; - cache_[cachekey] = entryNew; + TexCacheEntry *entryNew = new TexCacheEntry{}; + cache_[cachekey].reset(entryNew); if (hasClut && clutRenderAddress_ != 0xFFFFFFFF) { WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); } - entry = &cache_[cachekey]; + entry = entryNew; if (g_Config.bTextureBackoffCache) { entry->status = TexCacheEntry::STATUS_HASHING; } else { @@ -401,7 +401,7 @@ void TextureCacheCommon::Decimate() { ForgetLastTexture(); int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ) { - if (iter->second.lastFrame + killAge < gpuStats.numFlips) { + if (iter->second->lastFrame + killAge < gpuStats.numFlips) { DeleteTexture(iter++); } else { ++iter; @@ -416,9 +416,9 @@ void TextureCacheCommon::Decimate() { for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ) { // In low memory mode, we kill them all. - if (lowMemoryMode_ || iter->second.lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { - ReleaseTexture(&iter->second); - secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(&iter->second); + if (lowMemoryMode_ || iter->second->lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) { + ReleaseTexture(iter->second.get()); + secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(iter->second.get()); secondCache_.erase(iter++); } else { ++iter; @@ -471,8 +471,8 @@ bool TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c const u64 cachekeyMin = (u64)(entry->addr & 0x3FFFFFFF) << 32; const u64 cachekeyMax = cachekeyMin + (1ULL << 32); for (auto it = cache_.lower_bound(cachekeyMin), end = cache_.upper_bound(cachekeyMax); it != end; ++it) { - if (it->second.cluthash != entry->cluthash) { - it->second.status |= TexCacheEntry::STATUS_CLUT_RECHECK; + if (it->second->cluthash != entry->cluthash) { + it->second->status |= TexCacheEntry::STATUS_CLUT_RECHECK; } } } @@ -502,14 +502,14 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram fbCache_.push_back(framebuffer); } for (auto it = cache_.lower_bound(cacheKey), end = cache_.upper_bound(cacheKeyEnd); it != end; ++it) { - AttachFramebuffer(&it->second, addr, framebuffer); + AttachFramebuffer(it->second.get(), addr, framebuffer); } // Let's assume anything in mirrors is fair game to check. for (auto it = cache_.lower_bound(mirrorCacheKey), end = cache_.upper_bound(mirrorCacheKeyEnd); it != end; ++it) { const u64 mirrorlessKey = it->first & ~0x0060000000000000ULL; // Let's still make sure it's in the cache range. if (mirrorlessKey >= cacheKey && mirrorlessKey <= cacheKeyEnd) { - AttachFramebuffer(&it->second, addr, framebuffer); + AttachFramebuffer(it->second.get(), addr, framebuffer); } } break; @@ -524,7 +524,7 @@ void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *fram // We might erase, so move to the next one already (which won't become invalid.) ++it; - DetachFramebuffer(&cache_[cachekey], addr, framebuffer); + DetachFramebuffer(cache_[cachekey].get(), addr, framebuffer); } break; } @@ -746,7 +746,7 @@ bool TextureCacheCommon::SetOffsetTexture(u32 offset) { if (iter == cache_.end()) { return false; } - TexCacheEntry *entry = &iter->second; + TexCacheEntry *entry = iter->second.get(); bool success = false; for (size_t i = 0, n = fbCache_.size(); i < n; ++i) { @@ -1331,10 +1331,10 @@ void TextureCacheCommon::Clear(bool delete_them) { ForgetLastTexture(); if (delete_them) { for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { - ReleaseTexture(&iter->second); + ReleaseTexture(iter->second.get()); } for (TexCache::iterator iter = secondCache_.begin(); iter != secondCache_.end(); ++iter) { - ReleaseTexture(&iter->second); + ReleaseTexture(iter->second.get()); } } if (cache_.size() + secondCache_.size()) { @@ -1349,16 +1349,16 @@ void TextureCacheCommon::Clear(bool delete_them) { } void TextureCacheCommon::DeleteTexture(TexCache::iterator it) { - ReleaseTexture(&it->second); + ReleaseTexture(it->second.get()); auto fbInfo = fbTexInfo_.find(it->first); if (fbInfo != fbTexInfo_.end()) { fbTexInfo_.erase(fbInfo); } - cacheSizeEstimate_ -= EstimateTexMemoryUsage(&it->second); + cacheSizeEstimate_ -= EstimateTexMemoryUsage(it->second.get()); cache_.erase(it); } -bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { +bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) { bool hashFail = false; int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); @@ -1395,7 +1395,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelet u64 secondKey = fullhash | (u64)entry->cluthash << 32; TexCache::iterator secondIter = secondCache_.find(secondKey); if (secondIter != secondCache_.end()) { - TexCacheEntry *secondEntry = &secondIter->second; + TexCacheEntry *secondEntry = secondIter->second.get(); if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { // Reset the numInvalidated value lower, we got a match. if (entry->numInvalidated > 8) { @@ -1407,7 +1407,8 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *const entry, bool &doDelet } else { secondKey = entry->fullhash | ((u64)entry->cluthash << 32); secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache_[secondKey] = *entry; + // Is this wise? We simply copy the entry. + secondCache_[secondKey].reset(new TexCacheEntry(*entry)); doDelete = false; } } @@ -1439,27 +1440,27 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type } for (TexCache::iterator iter = cache_.lower_bound(startKey), end = cache_.upper_bound(endKey); iter != end; ++iter) { - u32 texAddr = iter->second.addr; - u32 texEnd = iter->second.addr + iter->second.sizeInRAM; + u32 texAddr = iter->second->addr; + u32 texEnd = iter->second->addr + iter->second->sizeInRAM; if (texAddr < addr_end && addr < texEnd) { - if (iter->second.GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - iter->second.SetHashStatus(TexCacheEntry::STATUS_HASHING); + if (iter->second->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { + iter->second->SetHashStatus(TexCacheEntry::STATUS_HASHING); } if (type != GPU_INVALIDATE_ALL) { gpuStats.numTextureInvalidations++; // Start it over from 0 (unless it's safe.) - iter->second.numFrames = type == GPU_INVALIDATE_SAFE ? 256 : 0; + iter->second->numFrames = type == GPU_INVALIDATE_SAFE ? 256 : 0; if (type == GPU_INVALIDATE_SAFE) { - u32 diff = gpuStats.numFlips - iter->second.lastFrame; + u32 diff = gpuStats.numFlips - iter->second->lastFrame; // We still need to mark if the texture is frequently changing, even if it's safely changing. if (diff < TEXCACHE_FRAME_CHANGE_FREQUENT) { - iter->second.status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; + iter->second->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; } } - iter->second.framesUntilNextFullHash = 0; - } else if (!iter->second.framebuffer) { - iter->second.invalidHint++; + iter->second->framesUntilNextFullHash = 0; + } else if (!iter->second->framebuffer) { + iter->second->invalidHint++; } } } @@ -1477,11 +1478,11 @@ void TextureCacheCommon::InvalidateAll(GPUInvalidationType /*unused*/) { timesInvalidatedAllThisFrame_++; for (TexCache::iterator iter = cache_.begin(), end = cache_.end(); iter != end; ++iter) { - if (iter->second.GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { - iter->second.SetHashStatus(TexCacheEntry::STATUS_HASHING); + if (iter->second->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { + iter->second->SetHashStatus(TexCacheEntry::STATUS_HASHING); } - if (!iter->second.framebuffer) { - iter->second.invalidHint++; + if (!iter->second->framebuffer) { + iter->second->invalidHint++; } } } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 40e21bdea5..1789d05e66 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -19,6 +19,7 @@ #include #include +#include #include "Common/CommonTypes.h" #include "Common/MemoryUtil.h" @@ -167,7 +168,7 @@ struct TexCacheEntry { class FramebufferManagerCommon; // Can't be unordered_map, we use lower_bound ... although for some reason that compiles on MSVC. -typedef std::map TexCache; +typedef std::map> TexCache; class TextureCacheCommon { public: @@ -214,7 +215,7 @@ protected: bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); virtual void BuildTexture(TexCacheEntry *const entry, bool replaceImages) = 0; virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0; - bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); + bool CheckFullHash(TexCacheEntry *entry, bool &doDelete); // Separate to keep main texture cache size down. struct AttachedFramebufferInfo {