From b3316fbe21054469fb0ee3318d6de6c4099281c1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 10 Jun 2022 02:17:44 +0200 Subject: [PATCH] Let VkTextureManager manage the VkHardwareTexture resources Let VkDescriptorSetManager manage the VkMaterial resources Add the resources to the delete list instead of freeing them immediately as the backend cannot rely on exactly when the hardware renderer decides to destroy them --- .../vulkan/renderer/vk_descriptorset.cpp | 25 ++++-- .../vulkan/renderer/vk_descriptorset.h | 10 ++- .../vulkan/system/vk_framebuffer.cpp | 18 ++--- .../vulkan/textures/vk_hwtexture.cpp | 78 ++++--------------- .../rendering/vulkan/textures/vk_hwtexture.h | 36 ++++----- .../vulkan/textures/vk_imagetransition.h | 15 ++-- .../vulkan/textures/vk_renderbuffers.cpp | 12 +-- .../rendering/vulkan/textures/vk_samplers.cpp | 2 +- .../rendering/vulkan/textures/vk_samplers.h | 2 +- .../rendering/vulkan/textures/vk_texture.cpp | 15 ++++ .../rendering/vulkan/textures/vk_texture.h | 8 ++ 11 files changed, 106 insertions(+), 115 deletions(-) diff --git a/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp b/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp index 8bac0f32b..dee835759 100644 --- a/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp @@ -41,6 +41,8 @@ VkDescriptorSetManager::VkDescriptorSetManager(VulkanFrameBuffer* fb) : fb(fb) VkDescriptorSetManager::~VkDescriptorSetManager() { + while (!Materials.empty()) + RemoveMaterial(Materials.back()); } void VkDescriptorSetManager::Init() @@ -115,8 +117,11 @@ void VkDescriptorSetManager::UpdateFixedSet() update.updateSets(fb->device); } -void VkDescriptorSetManager::TextureSetPoolReset() +void VkDescriptorSetManager::ResetHWTextureSets() { + for (auto mat : Materials) + mat->DeleteDescriptors(); + auto& deleteList = fb->GetCommands()->FrameDeleteList; for (auto& desc : TextureDescriptorPools) @@ -131,12 +136,6 @@ void VkDescriptorSetManager::TextureSetPoolReset() TextureDescriptorsLeft = 0; } -void VkDescriptorSetManager::FilterModeChanged() -{ - // Destroy the texture descriptors as they used the old samplers - VkMaterial::ResetAllDescriptors(); -} - void VkDescriptorSetManager::CreateNullTexture() { ImageBuilder imgbuilder; @@ -210,3 +209,15 @@ VulkanDescriptorSetLayout* VkDescriptorSetManager::GetTextureSetLayout(int numLa layout->SetDebugName("VkDescriptorSetManager.TextureSetLayout"); return layout.get(); } + +void VkDescriptorSetManager::AddMaterial(VkMaterial* texture) +{ + texture->it = Materials.insert(Materials.end(), texture); +} + +void VkDescriptorSetManager::RemoveMaterial(VkMaterial* texture) +{ + texture->DeleteDescriptors(); + texture->fb = nullptr; + Materials.erase(texture->it); +} diff --git a/src/common/rendering/vulkan/renderer/vk_descriptorset.h b/src/common/rendering/vulkan/renderer/vk_descriptorset.h index 66d81bc7a..1c4c564a1 100644 --- a/src/common/rendering/vulkan/renderer/vk_descriptorset.h +++ b/src/common/rendering/vulkan/renderer/vk_descriptorset.h @@ -2,8 +2,10 @@ #pragma once #include "vulkan/system/vk_objects.h" +#include class VulkanFrameBuffer; +class VkMaterial; class VkDescriptorSetManager { @@ -14,8 +16,7 @@ public: void Init(); void UpdateFixedSet(); void UpdateDynamicSet(); - void TextureSetPoolReset(); - void FilterModeChanged(); + void ResetHWTextureSets(); VulkanDescriptorSetLayout* GetDynamicSetLayout() { return DynamicSetLayout.get(); } VulkanDescriptorSetLayout* GetFixedSetLayout() { return FixedSetLayout.get(); } @@ -29,6 +30,9 @@ public: VulkanImageView* GetNullTextureView() { return NullTextureView.get(); } + void AddMaterial(VkMaterial* texture); + void RemoveMaterial(VkMaterial* texture); + private: void CreateDynamicSet(); void CreateFixedSet(); @@ -53,4 +57,6 @@ private: std::unique_ptr NullTexture; std::unique_ptr NullTextureView; + + std::list Materials; }; diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.cpp b/src/common/rendering/vulkan/system/vk_framebuffer.cpp index 052a1f7f2..754810f01 100644 --- a/src/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -86,7 +86,6 @@ VulkanFrameBuffer::~VulkanFrameBuffer() vkDeviceWaitIdle(device->device); // make sure the GPU is no longer using any objects before RAII tears them down // All descriptors must be destroyed before the descriptor pool in renderpass manager is destroyed - VkHardwareTexture::ResetAll(); VkHardwareBuffer::ResetAll(); PPResource::ResetAll(); @@ -258,12 +257,12 @@ void VulkanFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) IHardwareTexture *VulkanFrameBuffer::CreateHardwareTexture(int numchannels) { - return new VkHardwareTexture(numchannels); + return new VkHardwareTexture(this, numchannels); } FMaterial* VulkanFrameBuffer::CreateMaterial(FGameTexture* tex, int scaleflags) { - return new VkMaterial(tex, scaleflags); + return new VkMaterial(this, tex, scaleflags); } IVertexBuffer *VulkanFrameBuffer::CreateVertexBuffer() @@ -298,15 +297,15 @@ void VulkanFrameBuffer::SetTextureFilterMode() { if (mSamplerManager) { - mDescriptorSetManager->FilterModeChanged(); - mSamplerManager->FilterModeChanged(); + mDescriptorSetManager->ResetHWTextureSets(); + mSamplerManager->ResetHWSamplers(); } } void VulkanFrameBuffer::StartPrecaching() { // Destroy the texture descriptors to avoid problems with potentially stale textures. - VkMaterial::ResetAllDescriptors(); + mDescriptorSetManager->ResetHWTextureSets(); } void VulkanFrameBuffer::BlurScene(float amount) @@ -446,12 +445,7 @@ void VulkanFrameBuffer::InitLightmap(int LMTextureSize, int LMTextureCount, TArr int pixelsize = 8; auto& lightmap = mActiveRenderBuffers->Lightmap; - if (lightmap.Image) - { - GetCommands()->FrameDeleteList.Images.push_back(std::move(lightmap.Image)); - GetCommands()->FrameDeleteList.ImageViews.push_back(std::move(lightmap.View)); - lightmap.reset(); - } + lightmap.Reset(this); ImageBuilder builder; builder.setSize(w, h, 1, count); diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp index 3a0565fbc..ce3dd7b05 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.cpp @@ -31,39 +31,27 @@ #include "vulkan/system/vk_commandbuffer.h" #include "vulkan/textures/vk_samplers.h" #include "vulkan/textures/vk_renderbuffers.h" +#include "vulkan/textures/vk_texture.h" #include "vulkan/renderer/vk_descriptorset.h" #include "vulkan/renderer/vk_postprocess.h" #include "vulkan/shaders/vk_shader.h" #include "vk_hwtexture.h" -VkHardwareTexture *VkHardwareTexture::First = nullptr; - -VkHardwareTexture::VkHardwareTexture(int numchannels) +VkHardwareTexture::VkHardwareTexture(VulkanFrameBuffer* fb, int numchannels) : fb(fb) { mTexelsize = numchannels; - Next = First; - First = this; - if (Next) Next->Prev = this; + fb->GetTextureManager()->AddTexture(this); } VkHardwareTexture::~VkHardwareTexture() { - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - Reset(); -} - -void VkHardwareTexture::ResetAll() -{ - for (VkHardwareTexture *cur = VkHardwareTexture::First; cur; cur = cur->Next) - cur->Reset(); + if (fb) + fb->GetTextureManager()->RemoveTexture(this); } void VkHardwareTexture::Reset() { - if (auto fb = GetVulkanFrameBuffer()) + if (fb) { if (mappedSWFB) { @@ -71,15 +59,8 @@ void VkHardwareTexture::Reset() mappedSWFB = nullptr; } - auto &deleteList = fb->GetCommands()->FrameDeleteList; - if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image)); - if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View)); - for (auto &it : mImage.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second)); - if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image)); - if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View)); - for (auto &it : mDepthStencil.RSFramebuffers) deleteList.Framebuffers.push_back(std::move(it.second)); - mImage.reset(); - mDepthStencil.reset(); + mImage.Reset(fb); + mDepthStencil.Reset(fb); } } @@ -96,8 +77,6 @@ VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex) { if (!mDepthStencil.View) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = fb->GetBuffers()->SceneDepthStencilFormat; int w = tex->GetWidth(); int h = tex->GetHeight(); @@ -133,8 +112,6 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) } else { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; int w = tex->GetWidth(); int h = tex->GetHeight(); @@ -164,8 +141,6 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form if (w <= 0 || h <= 0) throw CVulkanError("Trying to create zero size texture"); - auto fb = GetVulkanFrameBuffer(); - int totalSize = w * h * pixelsize; BufferBuilder bufbuilder; @@ -234,8 +209,6 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) if (!mImage.Image) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = texelsize == 4 ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_R8_UNORM; ImageBuilder imgbuilder; @@ -283,8 +256,6 @@ unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) { - auto fb = GetVulkanFrameBuffer(); - VkFormat format = VK_FORMAT_B8G8R8A8_UNORM; ImageBuilder imgbuilder; @@ -331,28 +302,22 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) } } +///////////////////////////////////////////////////////////////////////////// -VkMaterial* VkMaterial::First = nullptr; - -VkMaterial::VkMaterial(FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags) +VkMaterial::VkMaterial(VulkanFrameBuffer* fb, FGameTexture* tex, int scaleflags) : FMaterial(tex, scaleflags), fb(fb) { - Next = First; - First = this; - if (Next) Next->Prev = this; + fb->GetDescriptorSetManager()->AddMaterial(this); } VkMaterial::~VkMaterial() { - if (Next) Next->Prev = Prev; - if (Prev) Prev->Next = Next; - else First = Next; - - DeleteDescriptors(); + if (fb) + fb->GetDescriptorSetManager()->RemoveMaterial(this); } void VkMaterial::DeleteDescriptors() { - if (auto fb = GetVulkanFrameBuffer()) + if (fb) { auto& deleteList = fb->GetCommands()->FrameDeleteList; @@ -360,19 +325,9 @@ void VkMaterial::DeleteDescriptors() { deleteList.Descriptors.push_back(std::move(it.descriptor)); } + + mDescriptorSets.clear(); } - - mDescriptorSets.clear(); -} - -void VkMaterial::ResetAllDescriptors() -{ - for (VkMaterial* cur = First; cur; cur = cur->Next) - cur->DeleteDescriptors(); - - auto fb = GetVulkanFrameBuffer(); - if (fb) - fb->GetDescriptorSetManager()->TextureSetPoolReset(); } VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) @@ -391,7 +346,6 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state) int numLayers = NumLayers(); - auto fb = GetVulkanFrameBuffer(); auto descriptor = fb->GetDescriptorSetManager()->AllocateTextureDescriptorSet(max(numLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS)); descriptor->SetDebugName("VkHardwareTexture.mDescriptorSets"); diff --git a/src/common/rendering/vulkan/textures/vk_hwtexture.h b/src/common/rendering/vulkan/textures/vk_hwtexture.h index 91bc5e1b7..030a97f52 100644 --- a/src/common/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/common/rendering/vulkan/textures/vk_hwtexture.h @@ -12,22 +12,23 @@ #include "volk/volk.h" #include "vk_imagetransition.h" #include "hw_material.h" +#include struct FMaterialState; class VulkanDescriptorSet; class VulkanImage; class VulkanImageView; class VulkanBuffer; +class VulkanFrameBuffer; class FGameTexture; class VkHardwareTexture : public IHardwareTexture { friend class VkMaterial; public: - VkHardwareTexture(int numchannels); + VkHardwareTexture(VulkanFrameBuffer* fb, int numchannels); ~VkHardwareTexture(); - static void ResetAll(); void Reset(); // Software renderer stuff @@ -41,6 +42,8 @@ public: VkTextureImage *GetImage(FTexture *tex, int translation, int flags); VkTextureImage *GetDepthStencil(FTexture *tex); + VulkanFrameBuffer* fb = nullptr; + std::list::iterator it; private: void CreateImage(FTexture *tex, int translation, int flags); @@ -48,10 +51,6 @@ private: void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels, bool mipmap); static int GetMipLevels(int w, int h); - static VkHardwareTexture *First; - VkHardwareTexture *Prev = nullptr; - VkHardwareTexture *Next = nullptr; - VkTextureImage mImage; int mTexelsize = 4; @@ -60,13 +59,20 @@ private: uint8_t* mappedSWFB = nullptr; }; - class VkMaterial : public FMaterial { - static VkMaterial* First; - VkMaterial* Prev = nullptr; - VkMaterial* Next = nullptr; +public: + VkMaterial(VulkanFrameBuffer* fb, FGameTexture* tex, int scaleflags); + ~VkMaterial(); + VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); + + void DeleteDescriptors() override; + + VulkanFrameBuffer* fb = nullptr; + std::list::iterator it; + +private: struct DescriptorEntry { int clampmode; @@ -82,12 +88,4 @@ class VkMaterial : public FMaterial }; std::vector mDescriptorSets; - -public: - VkMaterial(FGameTexture *tex, int scaleflags); - ~VkMaterial(); - VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state); - void DeleteDescriptors() override; - static void ResetAllDescriptors(); - -}; \ No newline at end of file +}; diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.h b/src/common/rendering/vulkan/textures/vk_imagetransition.h index c8071989a..4c6cde514 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.h +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.h @@ -3,20 +3,25 @@ #include "vulkan/system/vk_objects.h" #include "vulkan/system/vk_builders.h" +#include "vulkan/system/vk_framebuffer.h" +#include "vulkan/system/vk_commandbuffer.h" #include "vulkan/renderer/vk_renderpass.h" class VkTextureImage { public: - void reset() + void Reset(VulkanFrameBuffer* fb) { AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; Layout = VK_IMAGE_LAYOUT_UNDEFINED; - PPFramebuffer.reset(); + auto& deletelist = fb->GetCommands()->FrameDeleteList; + deletelist.Framebuffers.push_back(std::move(PPFramebuffer)); + for (auto &it : RSFramebuffers) + deletelist.Framebuffers.push_back(std::move(it.second)); RSFramebuffers.clear(); - DepthOnlyView.reset(); - View.reset(); - Image.reset(); + deletelist.ImageViews.push_back(std::move(DepthOnlyView)); + deletelist.ImageViews.push_back(std::move(View)); + deletelist.Images.push_back(std::move(Image)); } void GenerateMipmaps(VulkanCommandBuffer *cmdbuffer); diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp index 3bd67c98c..4c9fd2beb 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -88,7 +88,7 @@ void VkRenderBuffers::CreatePipeline(int width, int height) { for (int i = 0; i < NumPipelineImages; i++) { - PipelineImage[i].reset(); + PipelineImage[i].Reset(fb); } VkImageTransition barrier; @@ -113,10 +113,10 @@ void VkRenderBuffers::CreatePipeline(int width, int height) void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples) { - SceneColor.reset(); - SceneDepthStencil.reset(); - SceneNormal.reset(); - SceneFog.reset(); + SceneColor.Reset(fb); + SceneDepthStencil.Reset(fb); + SceneNormal.Reset(fb); + SceneFog.Reset(fb); CreateSceneColor(width, height, samples); CreateSceneDepthStencil(width, height, samples); @@ -219,7 +219,7 @@ void VkRenderBuffers::CreateShadowmap() if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality) return; - Shadowmap.reset(); + Shadowmap.Reset(fb); ImageBuilder builder; builder.setSize(gl_shadowmap_quality, 1024); diff --git a/src/common/rendering/vulkan/textures/vk_samplers.cpp b/src/common/rendering/vulkan/textures/vk_samplers.cpp index f6895b07a..b0ef4b518 100644 --- a/src/common/rendering/vulkan/textures/vk_samplers.cpp +++ b/src/common/rendering/vulkan/textures/vk_samplers.cpp @@ -75,7 +75,7 @@ VkSamplerManager::~VkSamplerManager() { } -void VkSamplerManager::FilterModeChanged() +void VkSamplerManager::ResetHWSamplers() { DeleteHWSamplers(); CreateHWSamplers(); diff --git a/src/common/rendering/vulkan/textures/vk_samplers.h b/src/common/rendering/vulkan/textures/vk_samplers.h index daa341cff..c630a944d 100644 --- a/src/common/rendering/vulkan/textures/vk_samplers.h +++ b/src/common/rendering/vulkan/textures/vk_samplers.h @@ -14,7 +14,7 @@ public: VkSamplerManager(VulkanFrameBuffer* fb); ~VkSamplerManager(); - void FilterModeChanged(); + void ResetHWSamplers(); VulkanSampler *Get(int no) const { return mSamplers[no].get(); } VulkanSampler* Get(PPFilterMode filter, PPWrapMode wrap); diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp index 0d485b662..9ce479605 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.cpp +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -21,6 +21,7 @@ */ #include "vk_texture.h" +#include "vk_hwtexture.h" VkTextureManager::VkTextureManager(VulkanFrameBuffer* fb) : fb(fb) { @@ -28,4 +29,18 @@ VkTextureManager::VkTextureManager(VulkanFrameBuffer* fb) : fb(fb) VkTextureManager::~VkTextureManager() { + while (!Textures.empty()) + RemoveTexture(Textures.back()); +} + +void VkTextureManager::AddTexture(VkHardwareTexture* texture) +{ + texture->it = Textures.insert(Textures.end(), texture); +} + +void VkTextureManager::RemoveTexture(VkHardwareTexture* texture) +{ + texture->Reset(); + texture->fb = nullptr; + Textures.erase(texture->it); } diff --git a/src/common/rendering/vulkan/textures/vk_texture.h b/src/common/rendering/vulkan/textures/vk_texture.h index a5e716b94..7d478ade8 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.h +++ b/src/common/rendering/vulkan/textures/vk_texture.h @@ -2,8 +2,11 @@ #pragma once #include "vulkan/system/vk_objects.h" +#include class VulkanFrameBuffer; +class VkHardwareTexture; +class VkMaterial; class VkTextureManager { @@ -11,6 +14,11 @@ public: VkTextureManager(VulkanFrameBuffer* fb); ~VkTextureManager(); + void AddTexture(VkHardwareTexture* texture); + void RemoveTexture(VkHardwareTexture* texture); + private: VulkanFrameBuffer* fb = nullptr; + + std::list Textures; };