diff --git a/src/common/textures/animtexture.cpp b/src/common/textures/animtexture.cpp index 7ec249025a..e1ebd1b6cc 100644 --- a/src/common/textures/animtexture.cpp +++ b/src/common/textures/animtexture.cpp @@ -50,7 +50,7 @@ void AnimTexture::SetFrame(const uint8_t *palette, const void *data_) { memcpy(Palette, palette, 768); memcpy(Image.Data(), data_, Width * Height); - CleanHardwareTextures(true); + CleanHardwareTextures(); } //=========================================================================== diff --git a/src/common/textures/hw_ihwtexture.h b/src/common/textures/hw_ihwtexture.h index 73023014cd..b207dceb4b 100644 --- a/src/common/textures/hw_ihwtexture.h +++ b/src/common/textures/hw_ihwtexture.h @@ -17,8 +17,6 @@ public: IHardwareTexture() = default; virtual ~IHardwareTexture() = default; - virtual void DeleteDescriptors() { } - virtual void AllocateBuffer(int w, int h, int texelsize) = 0; virtual uint8_t *MapBuffer() = 0; virtual unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) = 0; diff --git a/src/common/textures/hw_material.cpp b/src/common/textures/hw_material.cpp index d85b23f6ba..70e13fdc62 100644 --- a/src/common/textures/hw_material.cpp +++ b/src/common/textures/hw_material.cpp @@ -27,6 +27,7 @@ #include "hw_material.h" #include "texturemanager.h" #include "c_cvars.h" +#include "v_video.h" IHardwareTexture* CreateHardwareTexture(); @@ -173,7 +174,7 @@ FMaterial * FMaterial::ValidateTexture(FGameTexture * gtex, int scaleflags, bool FMaterial *hwtex = gtex->Material[scaleflags]; if (hwtex == NULL && create) { - hwtex = new FMaterial(gtex, scaleflags); + hwtex = screen->CreateMaterial(gtex, scaleflags); } return hwtex; } diff --git a/src/common/textures/hw_material.h b/src/common/textures/hw_material.h index bc9af78f0f..fddaa73f7b 100644 --- a/src/common/textures/hw_material.h +++ b/src/common/textures/hw_material.h @@ -27,10 +27,11 @@ public: FTexture* imgtex; // the first layer's texture image - should be moved into the array FMaterial(FGameTexture *tex, int scaleflags); - ~FMaterial(); + virtual ~FMaterial(); int GetLayerFlags() const { return mLayerFlags; } int GetShaderIndex() const { return mShaderIndex; } int GetScaleFlags() const { return mScaleFlags; } + virtual void DeleteDescriptors() { } FGameTexture* Source() const { diff --git a/src/common/textures/hw_texcontainer.h b/src/common/textures/hw_texcontainer.h index f7020b5b79..5876d6a2ca 100644 --- a/src/common/textures/hw_texcontainer.h +++ b/src/common/textures/hw_texcontainer.h @@ -36,11 +36,6 @@ private: hwTexture = nullptr; } - void DeleteDescriptors() - { - if (hwTexture) hwTexture->DeleteDescriptors(); - } - ~TranslatedTexture() { Delete(); @@ -81,15 +76,8 @@ private: } public: - - void Clean(bool reallyclean) + void Clean() { - hwDefTex[0].DeleteDescriptors(); - hwDefTex[1].DeleteDescriptors(); - for (unsigned int j = 0; j < hwTex_Translated.Size(); j++) - hwTex_Translated[j].DeleteDescriptors(); - - if (!reallyclean) return; hwDefTex[0].Delete(); hwDefTex[1].Delete(); hwTex_Translated.Clear(); diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index e8cf04505b..fcf1d871db 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -558,9 +558,9 @@ bool FTexture::DetermineTranslucency() } -void FTexture::CleanHardwareTextures(bool reallyclean) +void FTexture::CleanHardwareTextures() { - SystemTextures.Clean(reallyclean); + SystemTextures.Clean(); } //=========================================================================== @@ -787,6 +787,11 @@ void FGameTexture::SetSpriteRect() } +void FGameTexture::CleanHardwareData(bool full) +{ + +} + //=========================================================================== // // Create a hardware texture for this texture image. diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 7c71eda67a..6d6a0dbcf2 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -118,7 +118,7 @@ void FTextureManager::FlushAll() { for (int j = 0; j < 2; j++) { - Textures[i].Texture->GetTexture()->CleanHardwareTextures(true); + Textures[i].Texture->CleanHardwareData(); delete Textures[i].Texture->GetSoftwareTexture(); Textures[i].Texture->SetSoftwareTexture(nullptr); calcShouldUpscale(Textures[i].Texture); diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index 9b2f6e1c2a..d4e801b8f9 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -259,7 +259,7 @@ public: static FTexture *CreateTexture(int lumpnum, bool allowflats = false); virtual FImageSource *GetImage() const { return nullptr; } void CreateUpsampledTextureBuffer(FTextureBuffer &texbuffer, bool hasAlpha, bool checkonly); - void CleanHardwareTextures(bool reallyclean); + void CleanHardwareTextures(); int GetWidth() { return Width; } int GetHeight() { return Height; } @@ -648,6 +648,9 @@ public: else if ((isWarped() || shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE; return clampmode; } + + void CleanHardwareData(bool full = true); + }; inline FGameTexture* MakeGameTexture(FTexture* tex, const char *name, ETextureType useType) diff --git a/src/d_main.cpp b/src/d_main.cpp index 9cfb1582ff..11f514d8f5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -3401,6 +3401,7 @@ void D_Cleanup() DeinitMenus(); LightDefaults.DeleteAndClear(); // this can leak heap memory if it isn't cleared. TexAnim.DeleteAll(); + TexMan.DeleteAll(); // delete DoomStartupInfo data DoomStartupInfo.Name = ""; diff --git a/src/rendering/2d/f_wipe.cpp b/src/rendering/2d/f_wipe.cpp index 4797ab82c1..cf51b59cec 100644 --- a/src/rendering/2d/f_wipe.cpp +++ b/src/rendering/2d/f_wipe.cpp @@ -373,8 +373,8 @@ bool Wiper_Burn::Run(int ticks) done = (Density < 0); } - BurnTexture->CleanHardwareTextures(true); - endScreen->GetTexture()->CleanHardwareTextures(false); // this only cleans the descriptor sets for the Vulkan backend. Needs to be done better. + BurnTexture->CleanHardwareTextures(); + endScreen->CleanHardwareData(false); // this only cleans the descriptor sets for the Vulkan backend. We do not want to delete the wipe screen's hardware texture here. const uint8_t *src = BurnArray; uint32_t *dest = (uint32_t *)BurnTexture->GetBuffer(); diff --git a/src/rendering/hwrenderer/textures/hw_precache.cpp b/src/rendering/hwrenderer/textures/hw_precache.cpp index f3518bfb8c..55f92a8d4a 100644 --- a/src/rendering/hwrenderer/textures/hw_precache.cpp +++ b/src/rendering/hwrenderer/textures/hw_precache.cpp @@ -230,7 +230,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap &actorhitl // For now, only delete what's in neither list. The logic being used here does not really work that well for selective deletion. if (usedTextures.CheckKey(tex->GetTexture()) == nullptr && usedSprites.CheckKey(tex->GetTexture()) == nullptr) { - tex->GetTexture()->CleanHardwareTextures(true); + tex->CleanHardwareData(); } } } diff --git a/src/rendering/v_framebuffer.cpp b/src/rendering/v_framebuffer.cpp index d26dd03d6c..aa297fe9af 100644 --- a/src/rendering/v_framebuffer.cpp +++ b/src/rendering/v_framebuffer.cpp @@ -455,6 +455,11 @@ void DFrameBuffer::FPSLimit() } } +FMaterial* DFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) +{ + return new FMaterial(tex, scaleflags); +} + DEFINE_ACTION_FUNCTION(_Screen, GetViewWindow) { PARAM_PROLOGUE; diff --git a/src/rendering/v_video.h b/src/rendering/v_video.h index 080aed555a..29affa2510 100644 --- a/src/rendering/v_video.h +++ b/src/rendering/v_video.h @@ -65,6 +65,8 @@ class FFlatVertexBuffer; class HWViewpointBuffer; class FLightBuffer; struct HWDrawInfo; +class FMaterial; +class FGameTexture; enum EHWCaps { @@ -266,6 +268,7 @@ public: virtual IHardwareTexture *CreateHardwareTexture() { return nullptr; } virtual void PrecacheMaterial(FMaterial *mat, int translation) {} virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; } + virtual FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags); virtual void TextureFilterChanged() {} virtual void BeginFrame() {} virtual void SetWindowSize(int w, int h) {} diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index bb0270fba4..21e41efa73 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -434,8 +434,7 @@ void VkRenderState::ApplyMaterial() auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - VkHardwareTexture* base = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)) : nullptr; - VulkanDescriptorSet* descriptorset = base ? base->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet(); + VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet(); mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset); mMaterial.mChanged = false; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 83c43b6766..6524d486ff 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -667,6 +667,11 @@ IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture() return new VkHardwareTexture(); } +FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) +{ + return new VkMaterial(tex, scaleflags); +} + FModelRenderer *VulkanFrameBuffer::CreateModelRenderer(int mli) { return new FHWModelRenderer(nullptr, *GetRenderState(), mli); @@ -711,7 +716,7 @@ void VulkanFrameBuffer::TextureFilterChanged() if (mSamplerManager) { // Destroy the texture descriptors as they used the old samplers - VkHardwareTexture::ResetAllDescriptors(); + VkMaterial::ResetAllDescriptors(); mSamplerManager->SetTextureFilterMode(); } @@ -720,7 +725,7 @@ void VulkanFrameBuffer::TextureFilterChanged() void VulkanFrameBuffer::StartPrecaching() { // Destroy the texture descriptors to avoid problems with potentially stale textures. - VkHardwareTexture::ResetAllDescriptors(); + VkMaterial::ResetAllDescriptors(); } void VulkanFrameBuffer::BlurScene(float amount) diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 64dfa3e7bd..7ab7c6bc67 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -89,6 +89,7 @@ public: void PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) override; IHardwareTexture *CreateHardwareTexture() override; + FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags) override; FModelRenderer *CreateModelRenderer(int mli) override; IVertexBuffer *CreateVertexBuffer() override; IIndexBuffer *CreateIndexBuffer() override; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 3499cce3d8..a20be08ac1 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -64,8 +64,6 @@ void VkHardwareTexture::Reset() { if (auto fb = GetVulkanFrameBuffer()) { - ResetDescriptors(); - if (mappedSWFB) { mImage.Image->Unmap(); @@ -84,78 +82,6 @@ void VkHardwareTexture::Reset() } } -void VkHardwareTexture::ResetDescriptors() -{ - if (auto fb = GetVulkanFrameBuffer()) - { - auto &deleteList = fb->FrameDeleteList; - - for (auto &it : mDescriptorSets) - { - deleteList.Descriptors.push_back(std::move(it.descriptor)); - } - } - - mDescriptorSets.clear(); -} - -void VkHardwareTexture::ResetAllDescriptors() -{ - for (VkHardwareTexture *cur = First; cur; cur = cur->Next) - cur->ResetDescriptors(); - - auto fb = GetVulkanFrameBuffer(); - if (fb) - fb->GetRenderPassManager()->TextureSetPoolReset(); -} - -VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &state) -{ - FMaterial *mat = state.mMaterial; - auto base = state.mMaterial->Source(); - int clampmode = state.mClampMode; - int translation = state.mTranslation; - - clampmode = base->GetClampMode(clampmode); - - // Textures that are already scaled in the texture lump will not get replaced by hires textures. - int flags = mat->GetScaleFlags(); - - for (auto &set : mDescriptorSets) - { - if (set.descriptor && set.clampmode == clampmode && set.flags == flags) return set.descriptor.get(); - } - - int numLayers = mat->GetLayers(); - - auto fb = GetVulkanFrameBuffer(); - auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(std::max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); - - descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); - - VulkanSampler *sampler = fb->GetSamplerManager()->Get(clampmode); - - WriteDescriptors update; - update.addCombinedImageSampler(descriptor.get(), 0, GetImage(mat->BaseLayer(), translation, flags)->View.get(), sampler, mImage.Layout); - for (int i = 1; i < numLayers; i++) - { - FTexture *layer; - auto systex = static_cast(mat->GetLayer(i, 0, &layer)); - // fixme: Upscale flags must be disabled for certain layers. - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer, 0, flags)->View.get(), sampler, systex->mImage.Layout); - } - - auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); - for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) - { - update.addCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, mImage.Layout); - } - - update.updateSets(fb->device); - mDescriptorSets.emplace_back(clampmode, flags, std::move(descriptor)); - return mDescriptorSets.back().descriptor.get(); -} - VkTextureImage *VkHardwareTexture::GetImage(FTexture *tex, int translation, int flags) { if (!mImage.Image) @@ -392,3 +318,98 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) transition1.execute(fb->GetTransferCommands()); } } + + +VkMaterial* VkMaterial::First = nullptr; + +VkMaterial::VkMaterial(FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags) +{ + Next = First; + First = this; + if (Next) Next->Prev = this; +} + +VkMaterial::~VkMaterial() +{ + if (Next) Next->Prev = Prev; + if (Prev) Prev->Next = Next; + else First = Next; + + DeleteDescriptors(); +} + +void VkMaterial::DeleteDescriptors() +{ + if (auto fb = GetVulkanFrameBuffer()) + { + auto& deleteList = fb->FrameDeleteList; + + for (auto& it : mDescriptorSets) + { + deleteList.Descriptors.push_back(std::move(it.descriptor)); + } + } + + mDescriptorSets.clear(); +} + +void VkMaterial::ResetAllDescriptors() +{ + for (VkMaterial* cur = First; cur; cur = cur->Next) + cur->DeleteDescriptors(); + + auto fb = GetVulkanFrameBuffer(); + if (fb) + fb->GetRenderPassManager()->TextureSetPoolReset(); +} + +VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) +{ + auto base = Source(); + int clampmode = state.mClampMode; + int translation = state.mTranslation; + + auto remap = translation <= 0 ? nullptr : GPalette.TranslationToTable(translation); + if (remap) translation = remap->Index; + + clampmode = base->GetClampMode(clampmode); + + // Textures that are already scaled in the texture lump will not get replaced by hires textures. + int flags = GetScaleFlags(); + + for (auto& set : mDescriptorSets) + { + if (set.descriptor && set.clampmode == clampmode && set.flags == translation) return set.descriptor.get(); + } + + int numLayers = GetLayers(); + + auto fb = GetVulkanFrameBuffer(); + auto descriptor = fb->GetRenderPassManager()->AllocateTextureDescriptorSet(std::max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); + + descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); + + VulkanSampler* sampler = fb->GetSamplerManager()->Get(clampmode); + + WriteDescriptors update; + FTexture* layer; + auto systex = static_cast(GetLayer(0, translation, &layer)); + update.addCombinedImageSampler(descriptor.get(), 0, systex->GetImage(layer, translation, flags)->View.get(), sampler, systex->mImage.Layout); + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(GetLayer(i, 0, &layer)); + // fixme: Upscale flags must be disabled for certain layers. + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer, 0, flags)->View.get(), sampler, systex->mImage.Layout); + } + + auto dummyImage = fb->GetRenderPassManager()->GetNullTextureView(); + for (int i = numLayers; i < SHADER_MIN_REQUIRED_TEXTURE_LAYERS; i++) + { + update.addCombinedImageSampler(descriptor.get(), i, dummyImage, sampler, systex->mImage.Layout); + } + + update.updateSets(fb->device); + mDescriptorSets.emplace_back(clampmode, translation, std::move(descriptor)); + return mDescriptorSets.back().descriptor.get(); +} + diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index b7bd02979a..872f58aefa 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -11,15 +11,18 @@ #include "hw_ihwtexture.h" #include "volk/volk.h" #include "vk_imagetransition.h" +#include "hw_material.h" struct FMaterialState; class VulkanDescriptorSet; class VulkanImage; class VulkanImageView; class VulkanBuffer; +class FGameTexture; class VkHardwareTexture : public IHardwareTexture { + friend class VkMaterial; public: VkHardwareTexture(); ~VkHardwareTexture(); @@ -27,8 +30,6 @@ public: static void ResetAll(); void Reset(); - VulkanDescriptorSet *GetDescriptorSet(const FMaterialState &state); - // Software renderer stuff void AllocateBuffer(int w, int h, int texelsize) override; uint8_t *MapBuffer() override; @@ -37,12 +38,9 @@ public: // Wipe screen void CreateWipeTexture(int w, int h, const char *name); - void DeleteDescriptors() override { ResetDescriptors(); } - VkTextureImage *GetImage(FTexture *tex, int translation, int flags); VkTextureImage *GetDepthStencil(FTexture *tex); - static void ResetAllDescriptors(); private: void CreateImage(FTexture *tex, int translation, int flags); @@ -50,19 +48,32 @@ private: void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); static int GetMipLevels(int w, int h); - void ResetDescriptors(); - static VkHardwareTexture *First; VkHardwareTexture *Prev = nullptr; VkHardwareTexture *Next = nullptr; + VkTextureImage mImage; + int mTexelsize = 4; + + VkTextureImage mDepthStencil; + + uint8_t* mappedSWFB = nullptr; +}; + + +class VkMaterial : public FMaterial +{ + static VkMaterial* First; + VkMaterial* Prev = nullptr; + VkMaterial* Next = nullptr; + struct DescriptorEntry { int clampmode; int flags; std::unique_ptr descriptor; - DescriptorEntry(int cm, int f, std::unique_ptr &&d) + DescriptorEntry(int cm, int f, std::unique_ptr&& d) { clampmode = cm; flags = f; @@ -71,10 +82,12 @@ private: }; std::vector mDescriptorSets; - VkTextureImage mImage; - int mTexelsize = 4; - VkTextureImage mDepthStencil; +public: + VkMaterial(FGameTexture *tex, int scaleflags); + ~VkMaterial(); + VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); + void DeleteDescriptors() override; + static void ResetAllDescriptors(); - uint8_t* mappedSWFB = nullptr; -}; +}; \ No newline at end of file