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
This commit is contained in:
Magnus Norddahl 2022-06-10 02:17:44 +02:00 committed by Christoph Oelckers
parent 298c023b1d
commit b3316fbe21
11 changed files with 106 additions and 115 deletions

View File

@ -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);
}

View File

@ -2,8 +2,10 @@
#pragma once
#include "vulkan/system/vk_objects.h"
#include <list>
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<VulkanImage> NullTexture;
std::unique_ptr<VulkanImageView> NullTextureView;
std::list<VkMaterial*> Materials;
};

View File

@ -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);

View File

@ -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");

View File

@ -12,22 +12,23 @@
#include "volk/volk.h"
#include "vk_imagetransition.h"
#include "hw_material.h"
#include <list>
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<VkHardwareTexture*>::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<VkMaterial*>::iterator it;
private:
struct DescriptorEntry
{
int clampmode;
@ -82,12 +88,4 @@ class VkMaterial : public FMaterial
};
std::vector<DescriptorEntry> mDescriptorSets;
public:
VkMaterial(FGameTexture *tex, int scaleflags);
~VkMaterial();
VulkanDescriptorSet* GetDescriptorSet(const FMaterialState& state);
void DeleteDescriptors() override;
static void ResetAllDescriptors();
};
};

View File

@ -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);

View File

@ -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);

View File

@ -75,7 +75,7 @@ VkSamplerManager::~VkSamplerManager()
{
}
void VkSamplerManager::FilterModeChanged()
void VkSamplerManager::ResetHWSamplers()
{
DeleteHWSamplers();
CreateHWSamplers();

View File

@ -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);

View File

@ -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);
}

View File

@ -2,8 +2,11 @@
#pragma once
#include "vulkan/system/vk_objects.h"
#include <list>
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<VkHardwareTexture*> Textures;
};