diff --git a/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp b/src/common/rendering/vulkan/renderer/vk_descriptorset.cpp index 8bac0f32b7..dee8357590 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 66d81bc7a9..1c4c564a15 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 052a1f7f29..754810f016 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 3a0565fbc7..ce3dd7b052 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 91bc5e1b79..030a97f529 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 c8071989aa..4c6cde514e 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 3bd67c98ca..4c9fd2beb8 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 f6895b07ac..b0ef4b5187 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 daa341cfff..c630a944d1 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 0d485b6627..9ce4796052 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 a5e716b946..7d478ade86 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; };