From 3ad9783d8f18990ff427552924bbbd9dc51d5ee7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 21 Mar 2019 21:57:39 +0100 Subject: [PATCH] - fixed the hardware rendering precacher not to evict secondary layers of multi-layer textures. It will now check all layers of a material. Additionally it will also delete all descriptor sets of Vulkan hardware textures before precaching to make sure that nothing here can accidentally still reference a deleted texture. --- src/gamedata/fonts/v_font.h | 2 + src/gamedata/textures/textures.h | 1 + .../hwrenderer/textures/hw_material.h | 4 ++ .../hwrenderer/textures/hw_precache.cpp | 39 +++++++++++++++++-- .../hwrenderer/textures/hw_texcontainer.h | 9 ++++- .../vulkan/system/vk_framebuffer.cpp | 7 ++++ src/rendering/vulkan/system/vk_framebuffer.h | 1 + .../vulkan/textures/vk_hwtexture.cpp | 3 -- src/rendering/vulkan/textures/vk_hwtexture.h | 6 +++ src/v_video.h | 1 + 10 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/gamedata/fonts/v_font.h b/src/gamedata/fonts/v_font.h index a26b72044..724e4316e 100644 --- a/src/gamedata/fonts/v_font.h +++ b/src/gamedata/fonts/v_font.h @@ -119,6 +119,8 @@ public: void SetKerning(int c) { GlobalKerning = c; } bool NoTranslate() const { return noTranslate; } + + protected: FFont (int lump); diff --git a/src/gamedata/textures/textures.h b/src/gamedata/textures/textures.h index bc9d4811d..6f5e649fd 100644 --- a/src/gamedata/textures/textures.h +++ b/src/gamedata/textures/textures.h @@ -351,6 +351,7 @@ public: void CreateDefaultBrightmap(); bool FindHoles(const unsigned char * buffer, int w, int h); void SetUseType(ETextureType type) { UseType = type; } + ETextureType GetUseType() const { return UseType; } // Returns the whole texture, stored in column-major order virtual TArray Get8BitPixels(bool alphatex); diff --git a/src/rendering/hwrenderer/textures/hw_material.h b/src/rendering/hwrenderer/textures/hw_material.h index 154abcc89..98a0ebffe 100644 --- a/src/rendering/hwrenderer/textures/hw_material.h +++ b/src/rendering/hwrenderer/textures/hw_material.h @@ -136,6 +136,10 @@ public: static FMaterial *ValidateTexture(FTexture * tex, bool expand, bool create = true); static FMaterial *ValidateTexture(FTextureID no, bool expand, bool trans, bool create = true); + const TArray &GetLayerArray() const + { + return mTextureLayers; + } }; #endif diff --git a/src/rendering/hwrenderer/textures/hw_precache.cpp b/src/rendering/hwrenderer/textures/hw_precache.cpp index 3a1ea46c6..d5443805c 100644 --- a/src/rendering/hwrenderer/textures/hw_precache.cpp +++ b/src/rendering/hwrenderer/textures/hw_precache.cpp @@ -35,6 +35,7 @@ #include "hwrenderer/textures/hw_material.h" #include "image.h" #include "v_video.h" +#include "v_font.h" //========================================================================== @@ -169,18 +170,50 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl if (!modellist[i]) Models[i]->DestroyVertexBuffer(); } - // delete unused textures + TMap usedTextures, usedSprites; + + screen->StartPrecaching(); int cnt = TexMan.NumTextures(); + + // prepare the textures for precaching. First collect all used layer textures so that we know which ones should not be deleted. for (int i = cnt - 1; i >= 0; i--) { FTexture *tex = TexMan.ByIndex(i); if (tex != nullptr) { - if (!texhitlist[i]) + FMaterial *mat = FMaterial::ValidateTexture(tex, false, false); + if (mat != nullptr) + { + for (auto ftex : mat->GetLayerArray()) + { + usedTextures.Insert(ftex, true); + } + } + if (spritehitlist[i] != nullptr && (*spritehitlist[i]).CountUsed() > 0) + { + FMaterial *mat = FMaterial::ValidateTexture(tex, true, false); + if (mat != nullptr) + { + for (auto ftex : mat->GetLayerArray()) + { + usedSprites.Insert(ftex, true); + } + } + } + } + } + + // delete unused textures (i.e. those which didn't get referenced by any material in the cache list. + for (int i = cnt - 1; i >= 0; i--) + { + FTexture *tex = TexMan.ByIndex(i); + if (tex != nullptr && tex->GetUseType() != ETextureType::FontChar) + { + if (usedTextures.CheckKey(tex) == nullptr) { tex->SystemTextures.Clean(true, false); } - if (spritehitlist[i] == nullptr || (*spritehitlist[i]).CountUsed() == 0) + if (usedSprites.CheckKey(tex) == nullptr) { tex->SystemTextures.Clean(false, true); } diff --git a/src/rendering/hwrenderer/textures/hw_texcontainer.h b/src/rendering/hwrenderer/textures/hw_texcontainer.h index 65f356115..87df5ea87 100644 --- a/src/rendering/hwrenderer/textures/hw_texcontainer.h +++ b/src/rendering/hwrenderer/textures/hw_texcontainer.h @@ -88,7 +88,7 @@ public: tt->Delete(); tt->hwTexture =tex; } - + //=========================================================================== // // Deletes all allocated resources and considers translations @@ -125,6 +125,13 @@ public: } } + template + void Iterate(T callback) + { + for (auto & t : hwDefTex) if (t.hwTexture) callback(t.hwTexture); + for (auto & t : hwTex_Translated) if (t.hwTexture) callback(t.hwTexture); + } + }; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 3c72bbc0a..a71d7ea27 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -672,6 +672,13 @@ void VulkanFrameBuffer::TextureFilterChanged() } } +void VulkanFrameBuffer::StartPrecaching() +{ + // Destroy the texture descriptors to avoid problems with potentially stale textures. + for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next) + cur->ResetDescriptors(); +} + void VulkanFrameBuffer::BlurScene(float amount) { if (mPostprocess) diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index e26483ff9..6a169ec48 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -76,6 +76,7 @@ public: sector_t *RenderView(player_t *player) override; void SetTextureFilterMode() override; void TextureFilterChanged() override; + void StartPrecaching() override; void BeginFrame() override; void BlurScene(float amount) override; void PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) override; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index cb2e4bb90..e7e2c58e6 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -57,9 +57,6 @@ VkHardwareTexture::~VkHardwareTexture() if (fb) { auto &deleteList = fb->FrameDeleteList; - for (auto &it : mDescriptorSets) - deleteList.Descriptors.push_back(std::move(it.second)); - mDescriptorSets.clear(); if (mImage) deleteList.Images.push_back(std::move(mImage)); if (mImageView) deleteList.ImageViews.push_back(std::move(mImageView)); if (mStagingBuffer) deleteList.Buffers.push_back(std::move(mStagingBuffer)); diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 5066bf62e..d269b2a29 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -45,6 +45,12 @@ public: VulkanImage *GetImage(FTexture *tex, int translation, int flags); VulkanImageView *GetImageView(FTexture *tex, int translation, int flags); + static void ResetAllDescriptors() + { + for (VkHardwareTexture *cur = First; cur; cur = cur->Next) + cur->ResetDescriptors(); + } + private: void CreateImage(FTexture *tex, int translation, int flags); diff --git a/src/v_video.h b/src/v_video.h index 1634cc3a7..38ed46366 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -423,6 +423,7 @@ public: virtual void TextureFilterChanged() {} virtual void BeginFrame() {} virtual void SetWindowSize(int w, int h) {} + virtual void StartPrecaching() {} virtual int GetClientWidth() = 0; virtual int GetClientHeight() = 0;