- store the Vulkan descriptor sets in the material - where they belong!

Having them in the base texture object was a major maintenance issue.
This commit is contained in:
Christoph Oelckers 2020-04-18 23:56:22 +02:00
parent 46e75e8107
commit 5a2a72fc95
18 changed files with 160 additions and 116 deletions

View file

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

View file

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

View file

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

View file

@ -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
{

View file

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

View file

@ -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.

View file

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

View file

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

View file

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

View file

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

View file

@ -230,7 +230,7 @@ void hw_PrecacheTexture(uint8_t *texhitlist, TMap<PClassActor*, bool> &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();
}
}
}

View file

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

View file

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

View file

@ -434,8 +434,7 @@ void VkRenderState::ApplyMaterial()
auto fb = GetVulkanFrameBuffer();
auto passManager = fb->GetRenderPassManager();
VkHardwareTexture* base = mMaterial.mMaterial ? static_cast<VkHardwareTexture*>(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation)) : nullptr;
VulkanDescriptorSet* descriptorset = base ? base->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet();
VulkanDescriptorSet* descriptorset = mMaterial.mMaterial ? static_cast<VkMaterial*>(mMaterial.mMaterial)->GetDescriptorSet(mMaterial) : passManager->GetNullTextureDescriptorSet();
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptorset);
mMaterial.mChanged = false;

View file

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

View file

@ -89,6 +89,7 @@ public:
void PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) override;
IHardwareTexture *CreateHardwareTexture() override;
FMaterial* CreateMaterial(FGameTexture* tex, int scaleflags) override;
FModelRenderer *CreateModelRenderer(int mli) override;
IVertexBuffer *CreateVertexBuffer() override;
IIndexBuffer *CreateIndexBuffer() override;

View file

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

View file

@ -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<VulkanDescriptorSet> descriptor;
DescriptorEntry(int cm, int f, std::unique_ptr<VulkanDescriptorSet> &&d)
DescriptorEntry(int cm, int f, std::unique_ptr<VulkanDescriptorSet>&& d)
{
clampmode = cm;
flags = f;
@ -71,10 +82,12 @@ private:
};
std::vector<DescriptorEntry> 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;
};
};