From d33425d01dc4dcface48e6c1c392f00a69448876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 11 Jun 2026 10:57:30 +0200 Subject: [PATCH] Split out the CLUT texture cache from "TextureShaderCache" --- GPU/Common/TextureCacheCommon.cpp | 36 +++-- GPU/Common/TextureCacheCommon.h | 9 +- GPU/Common/TextureShaderCommon.cpp | 219 +++++++++++++++-------------- GPU/Common/TextureShaderCommon.h | 23 ++- GPU/D3D11/TextureCacheD3D11.cpp | 4 +- GPU/GLES/TextureCacheGLES.cpp | 6 +- GPU/GLES/TextureCacheGLES.h | 3 - GPU/GPUCommonHW.cpp | 4 +- GPU/Vulkan/TextureCacheVulkan.cpp | 8 +- 9 files changed, 168 insertions(+), 144 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5503436d2c..7b5270e2a1 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -92,7 +92,7 @@ static bool GetBestFramebufferCandidate(FramebufferManagerCommon *fbManager, con // These are Data::Format:: B4G4R4A4_PACK16, B5G6R6_PACK16, B5G5R5A1_PACK16, R8G8B8A8 TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D) - : draw_(draw), draw2D_(draw2D), replacer_(draw) { + : draw_(draw), draw2D_(draw2D), replacer_(draw), textureShaderCache_(draw, draw2D_) { decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; // It's only possible to have 1KB of palette entries, although we allow 2KB in a hack. @@ -111,13 +111,9 @@ TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D) // These buffers will grow if necessary, but most won't need more than this. tmpTexBuf32_.resize(512 * 512); // 1MB tmpTexBufRearrange_.resize(512 * 512); // 1MB - - textureShaderCache_ = new TextureShaderCache(draw, draw2D_); } TextureCacheCommon::~TextureCacheCommon() { - delete textureShaderCache_; - FreeAlignedMemory(clutBufConverted_); FreeAlignedMemory(clutBufRaw_); FreeAlignedMemory(expandClut_); @@ -125,7 +121,7 @@ TextureCacheCommon::~TextureCacheCommon() { void TextureCacheCommon::StartFrame() { ForgetLastTexture(); - textureShaderCache_->Decimate(); + clutTextureCache_.Decimate(); replacementTimeThisFrame_ = 0.0; float fps; @@ -2323,7 +2319,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer if (need_depalettize) { if (clutRenderAddress_ == 0xFFFFFFFF) { - clutTexture = textureShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBufRaw_); + clutTexture = clutTextureCache_.GetClutTexture(clutFormat, clutHash_, clutBufRaw_); smoothedDepal = CanUseSmoothDepal(gstate, fbFormat, clutTexture); } else { // The CLUT texture is dynamic, it's the framebuffer pointed to by clutRenderAddress. @@ -2376,7 +2372,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer depthUpperBits = (depth && framebuffer->fb_format == GE_FORMAT_8888) ? ((gstate.getTextureAddress(0) & 0x600000) >> 20) : 0; - textureShader = textureShaderCache_->GetDepalettizeShader(clutMode, texFormat, fbFormat, smoothedDepal, depthUpperBits); + textureShader = textureShaderCache_.GetDepalettizeShader(clutMode, texFormat, fbFormat, smoothedDepal, depthUpperBits); gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF); } @@ -2421,8 +2417,8 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer } else { draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::Aspect::COLOR_BIT, 0); } - Draw::SamplerState *nearest = textureShaderCache_->GetSampler(false); - Draw::SamplerState *clutSampler = textureShaderCache_->GetSampler(smoothedDepal); + Draw::SamplerState *nearest = textureShaderCache_.GetSampler(false); + Draw::SamplerState *clutSampler = textureShaderCache_.GetSampler(smoothedDepal); draw_->BindSamplerStates(0, 1, &nearest); draw_->BindSamplerStates(1, 1, &clutSampler); @@ -2490,7 +2486,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { framebufferManager_->BlitUsingRaster( dynamicClutTemp_, 0.0f, 0.0f, 512.0f, 1.0f, dynamicClutFbo_, 0.0f, 0.0f, scaleFactorX * 512.0f, 1.0f, false, 1.0f, reinterpret, "reinterpret_clut"); - Draw2DPipeline *textureShader = textureShaderCache_->GetDepalettizeShader(clutMode, GE_TFMT_CLUT8, GE_FORMAT_CLUT8, false, 0); + Draw2DPipeline *textureShader = textureShaderCache_.GetDepalettizeShader(clutMode, GE_TFMT_CLUT8, GE_FORMAT_CLUT8, false, 0); gstate_c.SetUseShaderDepal(ShaderDepalMode::OFF); int texWidth = gstate.getTextureWidth(0); @@ -2523,8 +2519,8 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { draw_->BindNativeTexture(0, GetNativeTextureView(entry, false)); draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::Aspect::COLOR_BIT, 0); - Draw::SamplerState *nearest = textureShaderCache_->GetSampler(false); - Draw::SamplerState *clutSampler = textureShaderCache_->GetSampler(false); + Draw::SamplerState *nearest = textureShaderCache_.GetSampler(false); + Draw::SamplerState *clutSampler = textureShaderCache_.GetSampler(false); draw_->BindSamplerStates(0, 1, &nearest); draw_->BindSamplerStates(1, 1, &clutSampler); @@ -2557,8 +2553,20 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); } +void TextureCacheCommon::DeviceLost() { + textureShaderCache_.DeviceLost(); + clutTextureCache_.DeviceLost(); + Clear(false); +} + +void TextureCacheCommon::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + textureShaderCache_.DeviceRestore(draw); + clutTextureCache_.DeviceRestore(draw); +} + void TextureCacheCommon::Clear(bool delete_them) { - textureShaderCache_->Clear(); + textureShaderCache_.Clear(); for (TexCache::iterator iter = cache_.begin(); iter != cache_.end(); ++iter) { ReleaseTexture(iter->second.get(), delete_them); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 1e85aa8309..751c5780e1 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -338,7 +338,7 @@ public: void InvalidateAll(GPUInvalidationType type); void ClearNextFrame(); - TextureShaderCache *GetTextureShaderCache() { return textureShaderCache_; } + TextureShaderCache &GetTextureShaderCache() { return textureShaderCache_; } virtual void ForgetLastTexture() = 0; virtual void Clear(bool delete_them); @@ -364,8 +364,8 @@ public: virtual void StartFrame(); - virtual void DeviceLost() = 0; - virtual void DeviceRestore(Draw::DrawContext *draw) = 0; + virtual void DeviceLost(); + virtual void DeviceRestore(Draw::DrawContext *draw); // Accessors for the debugger. virtual void *GetNativeTextureView(const TexCacheEntry *entry, bool flat) const = 0; @@ -480,7 +480,8 @@ protected: TextureReplacer replacer_; TextureScalerCommon scaler_; FramebufferManagerCommon *framebufferManager_; - TextureShaderCache *textureShaderCache_; + TextureShaderCache textureShaderCache_; + ClutTextureCache clutTextureCache_; ShaderManagerCommon *shaderManager_; bool clearCacheNextFrame_ = false; diff --git a/GPU/Common/TextureShaderCommon.cpp b/GPU/Common/TextureShaderCommon.cpp index f1efe5d0f6..cc0bf1f0c8 100644 --- a/GPU/Common/TextureShaderCommon.cpp +++ b/GPU/Common/TextureShaderCommon.cpp @@ -53,7 +53,120 @@ void TextureShaderCache::DeviceLost() { draw_ = nullptr; } -ClutTexture TextureShaderCache::GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, const u32 *rawClut) { +Draw::SamplerState *TextureShaderCache::GetSampler(bool linearFilter) { + if (linearFilter) { + if (!linearSampler_) { + Draw::SamplerStateDesc desc{}; + desc.magFilter = Draw::TextureFilter::LINEAR; + desc.minFilter = Draw::TextureFilter::LINEAR; + desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE; + desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE; + desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE; + linearSampler_ = draw_->CreateSamplerState(desc); + } + return linearSampler_; + } else { + if (!nearestSampler_) { + Draw::SamplerStateDesc desc{}; + desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE; + desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE; + desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE; + nearestSampler_ = draw_->CreateSamplerState(desc); + } + return nearestSampler_; + } +} + +void TextureShaderCache::Clear() { + for (auto shader = pipelineCache_.begin(); shader != pipelineCache_.end(); ++shader) { + if (shader->second->pipeline) { + shader->second->pipeline->Release(); + } + delete shader->second; + } + pipelineCache_.clear(); + if (nearestSampler_) { + nearestSampler_->Release(); + nearestSampler_ = nullptr; + } + if (linearSampler_) { + linearSampler_->Release(); + linearSampler_ = nullptr; + } +} + +Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal, u32 depthUpperBits) { + using namespace Draw; + + // Generate an ID for depal shaders. + u64 id = ((u64)depthUpperBits << 32) | (clutMode & 0xFFFFFF) | (textureFormat << 24) | (bufferFormat << 28); + + auto shader = pipelineCache_.find(id); + if (shader != pipelineCache_.end()) { + return shader->second; + } + + // TODO: Parse these out of clutMode some nice way, to become a bit more stateless. + DepalConfig config; + config.clutFormat = gstate.getClutPaletteFormat(); + config.startPos = gstate.getClutIndexStartPos(); + config.shift = gstate.getClutIndexShift(); + config.mask = gstate.getClutIndexMask(); + config.bufferFormat = bufferFormat; + config.textureFormat = textureFormat; + config.smoothedDepal = smoothedDepal; + config.depthUpperBits = depthUpperBits; + + Draw2DPipeline *ts = draw2D_->Create2DPipeline([config](ShaderWriter &writer) -> Draw2DPipelineInfo { + GenerateDepalFs(writer, config); + return Draw2DPipelineInfo{ + "depal", + config.bufferFormat == GE_FORMAT_DEPTH16 ? RASTER_DEPTH : RASTER_COLOR, + RASTER_COLOR, + samplers + }; + }); + + pipelineCache_[id] = ts; + + return ts->pipeline ? ts : nullptr; +} + +std::vector TextureShaderCache::DebugGetShaderIDs(DebugShaderType type) { + std::vector ids; + for (auto &entry : pipelineCache_) { + ids.push_back(StringFromFormat("%08x", entry.first)); + } + return ids; +} + +std::string TextureShaderCache::DebugGetShaderString(const std::string &idstr, DebugShaderType type, DebugShaderStringType stringType) { + uint32_t id = 0; + sscanf(idstr.c_str(), "%08x", &id); + auto iter = pipelineCache_.find(id); + if (iter == pipelineCache_.end()) + return ""; + switch (stringType) { + case SHADER_STRING_SHORT_DESC: + return idstr; + case SHADER_STRING_SOURCE_CODE: + return iter->second->code; + default: + return ""; + } +} + +void ClutTextureCache::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; +} + +void ClutTextureCache::DeviceLost() { + Clear(); + draw_ = nullptr; +} + +// TODO: We could cache many CLUTs in one big texture, might be more efficient. +ClutTexture ClutTextureCache::GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, const u32 *rawClut) { // Simplistic, but works well enough. u32 clutId = clutHash ^ (uint32_t)clutFormat; @@ -138,54 +251,15 @@ ClutTexture TextureShaderCache::GetClutTexture(GEPaletteFormat clutFormat, const return *tex; } -void TextureShaderCache::Clear() { - for (auto shader = depalCache_.begin(); shader != depalCache_.end(); ++shader) { - if (shader->second->pipeline) { - shader->second->pipeline->Release(); - } - delete shader->second; - } - depalCache_.clear(); +void ClutTextureCache::Clear() { for (auto tex = texCache_.begin(); tex != texCache_.end(); ++tex) { tex->second->texture->Release(); delete tex->second; } texCache_.clear(); - if (nearestSampler_) { - nearestSampler_->Release(); - nearestSampler_ = nullptr; - } - if (linearSampler_) { - linearSampler_->Release(); - linearSampler_ = nullptr; - } } -Draw::SamplerState *TextureShaderCache::GetSampler(bool linearFilter) { - if (linearFilter) { - if (!linearSampler_) { - Draw::SamplerStateDesc desc{}; - desc.magFilter = Draw::TextureFilter::LINEAR; - desc.minFilter = Draw::TextureFilter::LINEAR; - desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE; - desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE; - desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE; - linearSampler_ = draw_->CreateSamplerState(desc); - } - return linearSampler_; - } else { - if (!nearestSampler_) { - Draw::SamplerStateDesc desc{}; - desc.wrapU = Draw::TextureAddressMode::CLAMP_TO_EDGE; - desc.wrapV = Draw::TextureAddressMode::CLAMP_TO_EDGE; - desc.wrapW = Draw::TextureAddressMode::CLAMP_TO_EDGE; - nearestSampler_ = draw_->CreateSamplerState(desc); - } - return nearestSampler_; - } -} - -void TextureShaderCache::Decimate() { +void ClutTextureCache::Decimate() { for (auto tex = texCache_.begin(); tex != texCache_.end(); ) { if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.totals.numFlips) { tex->second->texture->Release(); @@ -197,64 +271,3 @@ void TextureShaderCache::Decimate() { } gpuStats.perFrame.numClutTextures = (int)texCache_.size(); } - -Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal, u32 depthUpperBits) { - using namespace Draw; - - // Generate an ID for depal shaders. - u64 id = ((u64)depthUpperBits << 32) | (clutMode & 0xFFFFFF) | (textureFormat << 24) | (bufferFormat << 28); - - auto shader = depalCache_.find(id); - if (shader != depalCache_.end()) { - return shader->second; - } - - // TODO: Parse these out of clutMode some nice way, to become a bit more stateless. - DepalConfig config; - config.clutFormat = gstate.getClutPaletteFormat(); - config.startPos = gstate.getClutIndexStartPos(); - config.shift = gstate.getClutIndexShift(); - config.mask = gstate.getClutIndexMask(); - config.bufferFormat = bufferFormat; - config.textureFormat = textureFormat; - config.smoothedDepal = smoothedDepal; - config.depthUpperBits = depthUpperBits; - - Draw2DPipeline *ts = draw2D_->Create2DPipeline([config](ShaderWriter &writer) -> Draw2DPipelineInfo { - GenerateDepalFs(writer, config); - return Draw2DPipelineInfo{ - "depal", - config.bufferFormat == GE_FORMAT_DEPTH16 ? RASTER_DEPTH : RASTER_COLOR, - RASTER_COLOR, - samplers - }; - }); - - depalCache_[id] = ts; - - return ts->pipeline ? ts : nullptr; -} - -std::vector TextureShaderCache::DebugGetShaderIDs(DebugShaderType type) { - std::vector ids; - for (auto &entry : depalCache_) { - ids.push_back(StringFromFormat("%08x", entry.first)); - } - return ids; -} - -std::string TextureShaderCache::DebugGetShaderString(const std::string &idstr, DebugShaderType type, DebugShaderStringType stringType) { - uint32_t id = 0; - sscanf(idstr.c_str(), "%08x", &id); - auto iter = depalCache_.find(id); - if (iter == depalCache_.end()) - return ""; - switch (stringType) { - case SHADER_STRING_SHORT_DESC: - return idstr; - case SHADER_STRING_SOURCE_CODE: - return iter->second->code; - default: - return ""; - } -} diff --git a/GPU/Common/TextureShaderCommon.h b/GPU/Common/TextureShaderCommon.h index 991d1ac35f..c342a87674 100644 --- a/GPU/Common/TextureShaderCommon.h +++ b/GPU/Common/TextureShaderCommon.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include @@ -36,6 +36,21 @@ public: int rampStarts[MAX_RAMPS]; }; +class ClutTextureCache { +public: + ClutTexture GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, const u32 *rawClut); + + void Clear(); + void Decimate(); + + void DeviceLost(); + void DeviceRestore(Draw::DrawContext *draw); + +private: + Draw::DrawContext *draw_; + std::unordered_map texCache_; +}; + // For CLUT depal shaders, and other pre-bind texture shaders. // Caches both shaders and palette textures. class TextureShaderCache { @@ -44,12 +59,10 @@ public: ~TextureShaderCache(); Draw2DPipeline *GetDepalettizeShader(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat, bool smoothedDepal, u32 depthUpperBits); - ClutTexture GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, const u32 *rawClut); Draw::SamplerState *GetSampler(bool linearFilter); void Clear(); - void Decimate(); std::vector DebugGetShaderIDs(DebugShaderType type); std::string DebugGetShaderString(const std::string &id, DebugShaderType type, DebugShaderStringType stringType); @@ -61,7 +74,5 @@ private: Draw::SamplerState *nearestSampler_ = nullptr; Draw::SamplerState *linearSampler_ = nullptr; Draw2D *draw2D_; - - std::map depalCache_; - std::map texCache_; + std::unordered_map pipelineCache_; }; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d2825d8428..aa364ff75a 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -175,13 +175,13 @@ void TextureCacheD3D11::DestroyDeviceObjects() { } void TextureCacheD3D11::DeviceLost() { - Clear(false); + TextureCacheCommon::DeviceLost(); DestroyDeviceObjects(); draw_ = nullptr; } void TextureCacheD3D11::DeviceRestore(Draw::DrawContext *draw) { - draw_ = draw; + TextureCacheCommon::DeviceRestore(draw); InitDeviceObjects(); } diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index b7634b09b5..ee0f31a584 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -413,16 +413,14 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, } void TextureCacheGLES::DeviceLost() { - textureShaderCache_->DeviceLost(); - Clear(false); + TextureCacheCommon::DeviceLost(); draw_ = nullptr; render_ = nullptr; } void TextureCacheGLES::DeviceRestore(Draw::DrawContext *draw) { - draw_ = draw; + TextureCacheCommon::DeviceRestore(draw); render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - textureShaderCache_->DeviceRestore(draw); } void *TextureCacheGLES::GetNativeTextureView(const TexCacheEntry *entry, bool flat) const { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 683e1ba3a0..6cdbf61894 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -40,9 +40,6 @@ public: void StartFrame() override; void SetFramebufferManager(FramebufferManagerGLES *fbManager); - void SetDepalShaderCache(TextureShaderCache *dpCache) { - textureShaderCache_ = dpCache; - } void SetDrawEngine(DrawEngineGLES *td) { drawEngine_ = td; } diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index fa396b9a84..d526e35255 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -651,7 +651,7 @@ std::vector GPUCommonHW::DebugGetShaderIDs(DebugShaderType type) { case SHADER_TYPE_VERTEXLOADER: return drawEngineCommon_->DebugGetVertexLoaderIDs(); case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); + return textureCache_->GetTextureShaderCache().DebugGetShaderIDs(type); default: return shaderManager_->DebugGetShaderIDs(type); } @@ -662,7 +662,7 @@ std::string GPUCommonHW::DebugGetShaderString(std::string id, DebugShaderType ty case SHADER_TYPE_VERTEXLOADER: return drawEngineCommon_->DebugGetVertexLoaderString(id, stringType); case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); + return textureCache_->GetTextureShaderCache().DebugGetShaderString(id, type, stringType); default: return shaderManager_->DebugGetShaderString(id, type, stringType); } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 99f2ab2092..5844cdc8d4 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -216,12 +216,10 @@ void TextureCacheVulkan::SetFramebufferManager(FramebufferManagerVulkan *fbManag } void TextureCacheVulkan::DeviceLost() { - textureShaderCache_->DeviceLost(); + TextureCacheCommon::DeviceLost(); VulkanContext *vulkan = draw_ ? (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT) : nullptr; - Clear(true); - samplerCache_.DeviceLost(); if (samplerNearest_) vulkan->Delete().QueueDeleteSampler(samplerNearest_); @@ -236,13 +234,11 @@ void TextureCacheVulkan::DeviceLost() { } void TextureCacheVulkan::DeviceRestore(Draw::DrawContext *draw) { - draw_ = draw; + TextureCacheCommon::DeviceRestore(draw); VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); _assert_(vulkan); - samplerCache_.DeviceRestore(vulkan); - textureShaderCache_->DeviceRestore(draw); VkSamplerCreateInfo samp{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; samp.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;