Add support for allocating and freeing slots in the bindless texture set
This commit is contained in:
parent
a9c1fdf23a
commit
6abe93a020
3 changed files with 111 additions and 38 deletions
|
|
@ -169,25 +169,23 @@ void VkDescriptorSetManager::ResetHWTextureSets()
|
|||
mat->DeleteDescriptors();
|
||||
|
||||
for (FSWColormap* colormap : Colormaps)
|
||||
colormap->Renderdev.bindIndex = -1;
|
||||
{
|
||||
if (colormap->Renderdev.bindIndex != -1)
|
||||
{
|
||||
FreeBindlessSlot(colormap->Renderdev.bindIndex);
|
||||
colormap->Renderdev.bindIndex = -1;
|
||||
}
|
||||
}
|
||||
Colormaps.clear();
|
||||
|
||||
for (int index : LightProbes)
|
||||
FreeBindlessSlot(index);
|
||||
LightProbes.clear();
|
||||
|
||||
Bindless.Writer = WriteDescriptors();
|
||||
Bindless.NextIndex = 0;
|
||||
|
||||
// Slot zero always needs to be the null texture
|
||||
AddBindlessTextureIndex(fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
|
||||
// And slot 1 is always our BRDF LUT texture
|
||||
AddBindlessTextureIndex(fb->GetTextureManager()->GetBrdfLutTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
|
||||
// Slot 2 is always our game palette texture
|
||||
AddBindlessTextureIndex(fb->GetTextureManager()->GetGamePaletteView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
|
||||
// Lightmap textures follow
|
||||
Bindless.NextIndex = LightmapsStart + MaxLightmaps;
|
||||
// Fixed indexes the shaders can always access
|
||||
SetBindlessTexture(0, fb->GetTextureManager()->GetNullTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
SetBindlessTexture(1, fb->GetTextureManager()->GetBrdfLutTextureView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
SetBindlessTexture(2, fb->GetTextureManager()->GetGamePaletteView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::AddMaterial(VkMaterial* texture)
|
||||
|
|
@ -406,7 +404,7 @@ void VkDescriptorSetManager::CreateBindlessSet()
|
|||
void VkDescriptorSetManager::UpdateBindlessDescriptorSet()
|
||||
{
|
||||
auto sampler = fb->GetSamplerManager()->LightmapSampler.get();
|
||||
int index = LightmapsStart;
|
||||
int index = FixedBindlessSlots;
|
||||
for (auto& lightmap : fb->GetTextureManager()->Lightmaps)
|
||||
{
|
||||
Bindless.Writer.AddCombinedImageSampler(Bindless.Set.get(), 0, index, lightmap.View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
|
@ -417,11 +415,47 @@ void VkDescriptorSetManager::UpdateBindlessDescriptorSet()
|
|||
Bindless.Writer = WriteDescriptors();
|
||||
}
|
||||
|
||||
int VkDescriptorSetManager::AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler)
|
||||
int VkDescriptorSetManager::AllocBindlessSlot(int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
int bucket = count - 1;
|
||||
|
||||
if (Bindless.FreeSlots.size() <= (size_t)bucket)
|
||||
Bindless.FreeSlots.resize(bucket + 1);
|
||||
|
||||
if (!Bindless.FreeSlots[bucket].empty())
|
||||
{
|
||||
int index = Bindless.FreeSlots[bucket].back();
|
||||
Bindless.FreeSlots[bucket].pop_back();
|
||||
return index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Bindless.NextIndex + count > MaxBindlessTextures)
|
||||
I_FatalError("Out of bindless texture slots!");
|
||||
int index = Bindless.NextIndex;
|
||||
if (Bindless.AllocSizes.size() < index + count)
|
||||
Bindless.AllocSizes.resize(index + count, 0);
|
||||
Bindless.AllocSizes[index] = count;
|
||||
Bindless.NextIndex += count;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::FreeBindlessSlot(int index)
|
||||
{
|
||||
if (index <= 0)
|
||||
return;
|
||||
|
||||
int bucket = Bindless.AllocSizes[index] - 1;
|
||||
Bindless.FreeSlots[bucket].push_back(index);
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::SetBindlessTexture(int index, VulkanImageView* imageview, VulkanSampler* sampler)
|
||||
{
|
||||
int index = Bindless.NextIndex++;
|
||||
Bindless.Writer.AddCombinedImageSampler(Bindless.Set.get(), 0, index, imageview, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
return index;
|
||||
}
|
||||
|
||||
int VkDescriptorSetManager::GetSWColormapTextureIndex(FSWColormap* colormap)
|
||||
|
|
@ -429,7 +463,8 @@ int VkDescriptorSetManager::GetSWColormapTextureIndex(FSWColormap* colormap)
|
|||
if (colormap->Renderdev.bindIndex != -1)
|
||||
return colormap->Renderdev.bindIndex;
|
||||
|
||||
colormap->Renderdev.bindIndex = AddBindlessTextureIndex(fb->GetTextureManager()->GetSWColormapView(colormap), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
colormap->Renderdev.bindIndex = AllocBindlessSlot(1);
|
||||
SetBindlessTexture(colormap->Renderdev.bindIndex, fb->GetTextureManager()->GetSWColormapView(colormap), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP));
|
||||
Colormaps.push_back(colormap);
|
||||
return colormap->Renderdev.bindIndex;
|
||||
}
|
||||
|
|
@ -447,8 +482,10 @@ int VkDescriptorSetManager::GetLightProbeTextureIndex(int probeIndex)
|
|||
if (textures->Irradiancemaps.size() > (size_t)probeIndex && textures->Irradiancemaps[probeIndex].View &&
|
||||
textures->Prefiltermaps.size() > (size_t)probeIndex && textures->Prefiltermaps[probeIndex].View)
|
||||
{
|
||||
LightProbes[probeIndex] = AddBindlessTextureIndex(textures->Irradiancemaps[probeIndex].View.get(), fb->GetSamplerManager()->IrradiancemapSampler.get());
|
||||
AddBindlessTextureIndex(textures->Prefiltermaps[probeIndex].View.get(), fb->GetSamplerManager()->PrefiltermapSampler.get());
|
||||
int bindIndex = AllocBindlessSlot(2);
|
||||
LightProbes[probeIndex] = bindIndex;
|
||||
SetBindlessTexture(bindIndex, textures->Irradiancemaps[probeIndex].View.get(), fb->GetSamplerManager()->IrradiancemapSampler.get());
|
||||
SetBindlessTexture(bindIndex + 1, textures->Prefiltermaps[probeIndex].View.get(), fb->GetSamplerManager()->PrefiltermapSampler.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,11 +43,14 @@ public:
|
|||
void RemoveMaterial(VkMaterial* texture);
|
||||
|
||||
void UpdateBindlessDescriptorSet();
|
||||
int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler);
|
||||
void SetBindlessTexture(int index, VulkanImageView* imageview, VulkanSampler* sampler);
|
||||
|
||||
int GetSWColormapTextureIndex(FSWColormap* colormap);
|
||||
int GetLightProbeTextureIndex(int probeIndex);
|
||||
|
||||
int AllocBindlessSlot(int count);
|
||||
void FreeBindlessSlot(int index);
|
||||
|
||||
private:
|
||||
void CreateLevelMeshLayout();
|
||||
void CreateRSBufferLayout();
|
||||
|
|
@ -69,6 +72,11 @@ private:
|
|||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
|
||||
static const int MaxFixedSets = 100;
|
||||
static const int MaxBindlessTextures = 16536;
|
||||
static const int FixedBindlessSlots = 3;
|
||||
static const int MaxLightmaps = 128;
|
||||
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> Layout;
|
||||
|
|
@ -96,7 +104,9 @@ private:
|
|||
std::unique_ptr<VulkanDescriptorSet> Set;
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> Layout;
|
||||
WriteDescriptors Writer;
|
||||
int NextIndex = 0;
|
||||
int NextIndex = FixedBindlessSlots + MaxLightmaps;
|
||||
std::vector<int> AllocSizes;
|
||||
std::vector<std::vector<int>> FreeSlots;
|
||||
} Bindless;
|
||||
|
||||
struct
|
||||
|
|
@ -128,9 +138,4 @@ private:
|
|||
std::list<VkMaterial*> Materials;
|
||||
std::vector<FSWColormap*> Colormaps;
|
||||
std::vector<int> LightProbes;
|
||||
|
||||
static const int MaxFixedSets = 100;
|
||||
static const int MaxBindlessTextures = 16536;
|
||||
static const int LightmapsStart = 3;
|
||||
static const int MaxLightmaps = 128;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -399,6 +399,11 @@ VkMaterial::~VkMaterial()
|
|||
|
||||
void VkMaterial::DeleteDescriptors()
|
||||
{
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
for (auto& set : mDescriptorSets)
|
||||
{
|
||||
descriptors->FreeBindlessSlot(set.bindlessIndex);
|
||||
}
|
||||
mDescriptorSets.clear();
|
||||
}
|
||||
|
||||
|
|
@ -432,15 +437,38 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
if (set.clampmode == clampmode && set.remap == translationp && set.globalShaderAddr == globalShaderAddr && set.indexed == state.mPaletteMode) return set;
|
||||
}
|
||||
|
||||
auto globalshader = GetGlobalShader(globalShaderAddr);
|
||||
int numLayersMat = *globalshader ? NumNonMaterialLayers() : NumLayers();
|
||||
const GlobalShaderDesc& globalshader = *GetGlobalShader(globalShaderAddr);
|
||||
int numLayersMat = globalshader ? NumNonMaterialLayers() : NumLayers();
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
auto* sampler = fb->GetSamplerManager()->Get(clampmode);
|
||||
|
||||
MaterialLayerInfo *layer;
|
||||
MaterialLayerInfo *layer = nullptr;
|
||||
auto systex = static_cast<VkHardwareTexture*>(GetLayer(0, state.mTranslation, &layer));
|
||||
|
||||
// How many textures do we need?
|
||||
int textureCount;
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
textureCount = numLayersMat;
|
||||
if (globalshader)
|
||||
{
|
||||
for (auto& texture : globalshader.CustomShaderTextures)
|
||||
{
|
||||
if (texture != nullptr)
|
||||
textureCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textureCount = 3;
|
||||
}
|
||||
|
||||
int bindlessIndex = descriptors->AllocBindlessSlot(textureCount);
|
||||
int texIndex = bindlessIndex;
|
||||
|
||||
auto systeximage = systex->GetImage(layer->layerTexture, state.mTranslation, layer->scaleFlags | paletteFlags);
|
||||
int bindlessIndex = descriptors->AddBindlessTextureIndex(systeximage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(0), clampmode));
|
||||
descriptors->SetBindlessTexture(texIndex++, systeximage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(0), clampmode));
|
||||
|
||||
if (!(layer->scaleFlags & CTF_Indexed))
|
||||
{
|
||||
|
|
@ -448,19 +476,19 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, 0, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags | paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
descriptors->SetBindlessTexture(texIndex++, syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
}
|
||||
|
||||
if(*globalshader)
|
||||
if(globalshader)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto& texture : globalshader->CustomShaderTextures)
|
||||
for (auto& texture : globalshader.CustomShaderTextures)
|
||||
{
|
||||
if (texture != nullptr)
|
||||
{
|
||||
VkHardwareTexture *tex = static_cast<VkHardwareTexture*>(texture.get()->GetHardwareTexture(0, 0));
|
||||
VkTextureImage *img = tex->GetImage(texture.get(), 0, paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(img->View.get(), fb->GetSamplerManager()->Get(globalshader->CustomShaderTextureSampling[i], clampmode));
|
||||
descriptors->SetBindlessTexture(texIndex++, img->View.get(), fb->GetSamplerManager()->Get(globalshader.CustomShaderTextureSampling[i], clampmode));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
|
@ -472,10 +500,13 @@ VkMaterial::DescriptorEntry& VkMaterial::GetDescriptorEntry(const FMaterialState
|
|||
{
|
||||
auto syslayer = static_cast<VkHardwareTexture*>(GetLayer(i, translation, &layer));
|
||||
auto syslayerimage = syslayer->GetImage(layer->layerTexture, 0, layer->scaleFlags | paletteFlags);
|
||||
descriptors->AddBindlessTextureIndex(syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
descriptors->SetBindlessTexture(texIndex++, syslayerimage->View.get(), fb->GetSamplerManager()->Get(GetLayerFilter(i), clampmode));
|
||||
}
|
||||
}
|
||||
|
||||
if (texIndex != bindlessIndex + textureCount)
|
||||
I_FatalError("VkMaterial.GetDescriptorEntry: texIndex != bindlessIndex + textureCount");
|
||||
|
||||
mDescriptorSets.emplace_back(clampmode, translationp, bindlessIndex, globalShaderAddr, state.mPaletteMode);
|
||||
return mDescriptorSets.back();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue