Index: ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp
===================================================================
--- ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp (revision 27510)
+++ ps/trunk/source/renderer/backend/vulkan/DescriptorManager.cpp (revision 27511)
@@ -1,365 +1,383 @@
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "DescriptorManager.h"
#include "lib/hash.h"
#include "ps/containers/StaticVector.h"
#include "renderer/backend/vulkan/Device.h"
#include "renderer/backend/vulkan/Mapping.h"
#include "renderer/backend/vulkan/Texture.h"
#include "renderer/backend/vulkan/Utilities.h"
#include
#include
namespace Renderer
{
namespace Backend
{
namespace Vulkan
{
CDescriptorManager::CDescriptorManager(CDevice* device, const bool useDescriptorIndexing)
- : m_Device(device), m_UseDescriptorIndexing(useDescriptorIndexing)
+ : m_Device(device), m_UseDescriptorIndexing(useDescriptorIndexing),
+ m_ErrorTexture(device->CreateTexture(
+ "DescriptorManagerErrorTexture", ITexture::Type::TEXTURE_2D,
+ ITexture::Usage::TRANSFER_DST | ITexture::Usage::SAMPLED,
+ Format::R8G8B8A8_UNORM, 1, 1,
+ Sampler::MakeDefaultSampler(Sampler::Filter::NEAREST, Sampler::AddressMode::REPEAT),
+ 1, 1))
{
if (useDescriptorIndexing)
{
VkDescriptorPoolSize descriptorPoolSize{};
descriptorPoolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorPoolSize.descriptorCount = DESCRIPTOR_INDEXING_BINDING_SIZE * NUMBER_OF_BINDINGS_PER_DESCRIPTOR_INDEXING_SET;
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{};
descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolCreateInfo.poolSizeCount = 1;
descriptorPoolCreateInfo.pPoolSizes = &descriptorPoolSize;
descriptorPoolCreateInfo.maxSets = 1;
descriptorPoolCreateInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
ENSURE_VK_SUCCESS(vkCreateDescriptorPool(
device->GetVkDevice(), &descriptorPoolCreateInfo, nullptr, &m_DescriptorIndexingPool));
const VkShaderStageFlags stageFlags =
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
const std::array bindings{{
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, DESCRIPTOR_INDEXING_BINDING_SIZE, stageFlags},
{1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, DESCRIPTOR_INDEXING_BINDING_SIZE, stageFlags},
{2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, DESCRIPTOR_INDEXING_BINDING_SIZE, stageFlags}
}};
const VkDescriptorBindingFlagsEXT baseBindingFlags =
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT
| VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT;
const std::array bindingFlags{{
baseBindingFlags, baseBindingFlags, baseBindingFlags
}};
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingFlagsCreateInfo{};
bindingFlagsCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
bindingFlagsCreateInfo.bindingCount = bindingFlags.size();
bindingFlagsCreateInfo.pBindingFlags = bindingFlags.data();
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{};
descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptorSetLayoutCreateInfo.bindingCount = bindings.size();
descriptorSetLayoutCreateInfo.pBindings = bindings.data();
descriptorSetLayoutCreateInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
descriptorSetLayoutCreateInfo.pNext = &bindingFlagsCreateInfo;
ENSURE_VK_SUCCESS(vkCreateDescriptorSetLayout(
device->GetVkDevice(), &descriptorSetLayoutCreateInfo,
nullptr, &m_DescriptorIndexingSetLayout));
m_DescriptorSetLayouts.emplace_back(m_DescriptorIndexingSetLayout);
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{};
descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
descriptorSetAllocateInfo.descriptorPool = m_DescriptorIndexingPool;
descriptorSetAllocateInfo.descriptorSetCount = 1;
descriptorSetAllocateInfo.pSetLayouts = &m_DescriptorIndexingSetLayout;
ENSURE_VK_SUCCESS(vkAllocateDescriptorSets(
device->GetVkDevice(), &descriptorSetAllocateInfo, &m_DescriptorIndexingSet));
for (DescriptorIndexingBindingMap& bindingMap : m_DescriptorIndexingBindings)
{
bindingMap.firstFreeIndex = 0;
bindingMap.elements.resize(DESCRIPTOR_INDEXING_BINDING_SIZE);
std::iota(bindingMap.elements.begin(), std::prev(bindingMap.elements.end()), 1);
bindingMap.elements.back() = -1;
}
}
// Currently we hard-code the layout for uniforms.
const VkDescriptorSetLayoutBinding bindings[] =
{
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT}
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{};
descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptorSetLayoutCreateInfo.bindingCount = std::size(bindings);
descriptorSetLayoutCreateInfo.pBindings = bindings;
ENSURE_VK_SUCCESS(vkCreateDescriptorSetLayout(
device->GetVkDevice(), &descriptorSetLayoutCreateInfo,
nullptr, &m_UniformDescriptorSetLayout));
m_DescriptorSetLayouts.emplace_back(m_UniformDescriptorSetLayout);
}
CDescriptorManager::~CDescriptorManager()
{
VkDevice device = m_Device->GetVkDevice();
for (auto& pair: m_SingleTypePools)
{
for (SingleTypePool& pool : pair.second)
{
if (pool.pool != VK_NULL_HANDLE)
vkDestroyDescriptorPool(device, pool.pool, nullptr);
if (pool.layout != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(device, pool.layout, nullptr);
}
}
m_SingleTypePools.clear();
for (VkDescriptorSetLayout descriptorSetLayout : m_DescriptorSetLayouts)
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
m_DescriptorSetLayouts.clear();
if (m_DescriptorIndexingPool != VK_NULL_HANDLE)
vkDestroyDescriptorPool(device, m_DescriptorIndexingPool, nullptr);
}
CDescriptorManager::SingleTypePool& CDescriptorManager::GetSingleTypePool(
const VkDescriptorType type, const uint32_t size)
{
ENSURE(size > 0 && size <= 16);
std::vector& pools = m_SingleTypePools[type];
if (pools.size() <= size)
pools.resize(size + 1);
SingleTypePool& pool = pools[size];
if (pool.pool == VK_NULL_HANDLE)
{
constexpr uint32_t maxSets = 16384;
VkDescriptorPoolSize descriptorPoolSize{};
descriptorPoolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorPoolSize.descriptorCount = maxSets * size;
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{};
descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolCreateInfo.poolSizeCount = 1;
descriptorPoolCreateInfo.pPoolSizes = &descriptorPoolSize;
descriptorPoolCreateInfo.maxSets = maxSets;
ENSURE_VK_SUCCESS(vkCreateDescriptorPool(
m_Device->GetVkDevice(), &descriptorPoolCreateInfo, nullptr, &pool.pool));
const VkPipelineStageFlags stageFlags =
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
PS::StaticVector bindings;
for (uint32_t index = 0; index < size; ++index)
bindings.emplace_back(VkDescriptorSetLayoutBinding{index, type, 1, stageFlags});
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{};
descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptorSetLayoutCreateInfo.bindingCount = size;
descriptorSetLayoutCreateInfo.pBindings = bindings.data();
ENSURE_VK_SUCCESS(vkCreateDescriptorSetLayout(
m_Device->GetVkDevice(), &descriptorSetLayoutCreateInfo, nullptr, &pool.layout));
pool.firstFreeIndex = 0;
pool.elements.reserve(maxSets);
for (uint32_t index = 0; index < maxSets; ++index)
- pool.elements.push_back({VK_NULL_HANDLE, static_cast(index + 1)});
- pool.elements.back().second = -1;
+ pool.elements.push_back({VK_NULL_HANDLE, 1, static_cast(index + 1)});
+ pool.elements.back().nextFreeIndex = SingleTypePool::INVALID_INDEX;
}
return pool;
}
VkDescriptorSetLayout CDescriptorManager::GetSingleTypeDescritorSetLayout(
VkDescriptorType type, const uint32_t size)
{
return GetSingleTypePool(type, size).layout;
}
size_t CDescriptorManager::SingleTypeCacheKeyHash::operator()(const SingleTypeCacheKey& key) const
{
size_t seed = 0;
hash_combine(seed, key.first);
for (CTexture::UID uid : key.second)
hash_combine(seed, uid);
return seed;
}
VkDescriptorSet CDescriptorManager::GetSingleTypeDescritorSet(
VkDescriptorType type, VkDescriptorSetLayout layout,
const std::vector& texturesUID,
const std::vector& textures)
{
ENSURE(texturesUID.size() == textures.size());
ENSURE(!texturesUID.empty());
const SingleTypeCacheKey key{layout, texturesUID};
auto it = m_SingleTypeSets.find(key);
if (it == m_SingleTypeSets.end())
{
SingleTypePool& pool = GetSingleTypePool(type, texturesUID.size());
const int16_t elementIndex = pool.firstFreeIndex;
- ENSURE(elementIndex != -1);
- std::pair& element = pool.elements[elementIndex];
- pool.firstFreeIndex = element.second;
+ ENSURE(elementIndex != SingleTypePool::INVALID_INDEX);
+ SingleTypePool::Element& element = pool.elements[elementIndex];
+ ENSURE(pool.firstFreeIndex != element.nextFreeIndex);
+ pool.firstFreeIndex = element.nextFreeIndex;
+ ++element.version;
+ // Occupy the index.
+ element.nextFreeIndex = SingleTypePool::INVALID_INDEX;
- if (element.first == VK_NULL_HANDLE)
+ if (element.set == VK_NULL_HANDLE)
{
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{};
descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
descriptorSetAllocateInfo.descriptorPool = pool.pool;
descriptorSetAllocateInfo.descriptorSetCount = 1;
descriptorSetAllocateInfo.pSetLayouts = &layout;
ENSURE_VK_SUCCESS(vkAllocateDescriptorSets(
- m_Device->GetVkDevice(), &descriptorSetAllocateInfo, &element.first));
+ m_Device->GetVkDevice(), &descriptorSetAllocateInfo, &element.set));
}
- it = m_SingleTypeSets.emplace(key, element.first).first;
+ it = m_SingleTypeSets.emplace(key, element.set).first;
for (const CTexture::UID uid : texturesUID)
- m_TextureSingleTypePoolMap[uid].push_back({type, static_cast(texturesUID.size()), elementIndex});
+ if (uid != CTexture::INVALID_UID)
+ m_TextureSingleTypePoolMap[uid].push_back({type, element.version, elementIndex, static_cast(texturesUID.size())});
PS::StaticVector infos;
- PS::StaticVector writes;
- for (size_t index = 0; index < textures.size(); ++index)
+ for (CTexture* texture : textures)
{
- if (!textures[index])
- continue;
- ENSURE(textures[index]->GetUsage() & ITexture::Usage::SAMPLED);
+ if (!texture)
+ texture = m_ErrorTexture->As();
+ ENSURE(texture->GetUsage() & ITexture::Usage::SAMPLED);
VkDescriptorImageInfo descriptorImageInfo{};
descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- descriptorImageInfo.imageView = textures[index]->GetSamplerImageView();
- descriptorImageInfo.sampler = textures[index]->GetSampler();
+ descriptorImageInfo.imageView = texture->GetSamplerImageView();
+ descriptorImageInfo.sampler = texture->GetSampler();
infos.emplace_back(std::move(descriptorImageInfo));
-
- VkWriteDescriptorSet writeDescriptorSet{};
- writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- writeDescriptorSet.dstSet = element.first;
- writeDescriptorSet.dstBinding = index;
- writeDescriptorSet.dstArrayElement = 0;
- writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- writeDescriptorSet.descriptorCount = 1;
- writeDescriptorSet.pImageInfo = &infos.back();
- writes.emplace_back(std::move(writeDescriptorSet));
}
+ VkWriteDescriptorSet writeDescriptorSet{};
+ writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ writeDescriptorSet.dstSet = element.set;
+ writeDescriptorSet.dstBinding = 0;
+ writeDescriptorSet.dstArrayElement = 0;
+ writeDescriptorSet.descriptorType = type;
+ writeDescriptorSet.descriptorCount = static_cast(infos.size());
+ writeDescriptorSet.pImageInfo = infos.data();
+
vkUpdateDescriptorSets(
- m_Device->GetVkDevice(), writes.size(), writes.data(), 0, nullptr);
+ m_Device->GetVkDevice(), 1, &writeDescriptorSet, 0, nullptr);
}
return it->second;
}
uint32_t CDescriptorManager::GetUniformSet() const
{
return m_UseDescriptorIndexing ? 1 : 0;
}
uint32_t CDescriptorManager::GetTextureDescriptor(CTexture* texture)
{
ENSURE(m_UseDescriptorIndexing);
ENSURE(texture->GetUsage() & ITexture::Usage::SAMPLED);
uint32_t binding = 0;
if (texture->GetType() == ITexture::Type::TEXTURE_2D &&
IsDepthFormat(texture->GetFormat()) &&
texture->IsCompareEnabled())
binding = 2;
else if (texture->GetType() == ITexture::Type::TEXTURE_CUBE)
binding = 1;
DescriptorIndexingBindingMap& bindingMap = m_DescriptorIndexingBindings[binding];
auto it = bindingMap.map.find(texture->GetUID());
if (it != bindingMap.map.end())
return it->second;
m_TextureToBindingMap[texture->GetUID()] = binding;
ENSURE(bindingMap.firstFreeIndex != -1);
uint32_t descriptorSetIndex = bindingMap.firstFreeIndex;
bindingMap.firstFreeIndex = bindingMap.elements[bindingMap.firstFreeIndex];
ENSURE(texture->GetType() != ITexture::Type::TEXTURE_2D_MULTISAMPLE);
VkDescriptorImageInfo descriptorImageInfo{};
descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
descriptorImageInfo.imageView = texture->GetSamplerImageView();
descriptorImageInfo.sampler = texture->GetSampler();
VkWriteDescriptorSet writeDescriptorSet{};
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeDescriptorSet.dstSet = m_DescriptorIndexingSet;
writeDescriptorSet.dstBinding = binding;
writeDescriptorSet.dstArrayElement = descriptorSetIndex;
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
writeDescriptorSet.descriptorCount = 1;
writeDescriptorSet.pImageInfo = &descriptorImageInfo;
vkUpdateDescriptorSets(
m_Device->GetVkDevice(), 1, &writeDescriptorSet, 0, nullptr);
bindingMap.map[texture->GetUID()] = descriptorSetIndex;
return descriptorSetIndex;
}
void CDescriptorManager::OnTextureDestroy(const CTexture::UID uid)
{
+ ENSURE(uid != CTexture::INVALID_UID);
if (m_UseDescriptorIndexing)
{
DescriptorIndexingBindingMap& bindingMap =
m_DescriptorIndexingBindings[m_TextureToBindingMap[uid]];
auto it = bindingMap.map.find(uid);
// It's possible to not have the texture in the map. Because a texture will
// be added to it only in case of usage.
if (it == bindingMap.map.end())
return;
const int16_t index = it->second;
bindingMap.elements[index] = bindingMap.firstFreeIndex;
bindingMap.firstFreeIndex = index;
+ bindingMap.map.erase(it);
}
else
{
auto it = m_TextureSingleTypePoolMap.find(uid);
if (it == m_TextureSingleTypePoolMap.end())
return;
for (const auto& entry : it->second)
{
- SingleTypePool& pool = GetSingleTypePool(std::get<0>(entry), std::get<1>(entry));
- const int16_t elementIndex = std::get<2>(entry);
- pool.elements[elementIndex].second = pool.firstFreeIndex;
- pool.firstFreeIndex = elementIndex;
+ SingleTypePool& pool = GetSingleTypePool(entry.type, entry.size);
+ SingleTypePool::Element& element = pool.elements[entry.elementIndex];
+ // Multiple textures might be used by the same descriptor set and
+ // we don't need to reset it if it was already.
+ if (element.version == entry.version && element.nextFreeIndex == SingleTypePool::INVALID_INDEX)
+ {
+ ENSURE(pool.firstFreeIndex != entry.elementIndex);
+ element.nextFreeIndex = pool.firstFreeIndex;
+ pool.firstFreeIndex = entry.elementIndex;
+ }
}
+ m_TextureSingleTypePoolMap.erase(it);
}
}
} // namespace Vulkan
} // namespace Backend
} // namespace Renderer
Index: ps/trunk/source/renderer/backend/vulkan/DescriptorManager.h
===================================================================
--- ps/trunk/source/renderer/backend/vulkan/DescriptorManager.h (revision 27510)
+++ ps/trunk/source/renderer/backend/vulkan/DescriptorManager.h (revision 27511)
@@ -1,124 +1,140 @@
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_RENDERER_BACKEND_VULKAN_DESCRIPTORMANAGER
#define INCLUDED_RENDERER_BACKEND_VULKAN_DESCRIPTORMANAGER
#include "renderer/backend/Sampler.h"
#include "renderer/backend/vulkan/Texture.h"
#include
#include
#include
#include
#include
#include
namespace Renderer
{
namespace Backend
{
namespace Vulkan
{
class CDevice;
class CDescriptorManager
{
public:
CDescriptorManager(CDevice* device, const bool useDescriptorIndexing);
~CDescriptorManager();
bool UseDescriptorIndexing() const { return m_UseDescriptorIndexing; }
/**
* @return a single type descriptor set layout with the number of bindings
* equals to the size. The returned layout is owned by the manager.
*/
VkDescriptorSetLayout GetSingleTypeDescritorSetLayout(
VkDescriptorType type, const uint32_t size);
VkDescriptorSet GetSingleTypeDescritorSet(
VkDescriptorType type, VkDescriptorSetLayout layout,
const std::vector& texturesUID,
const std::vector& textures);
uint32_t GetUniformSet() const;
uint32_t GetTextureDescriptor(CTexture* texture);
void OnTextureDestroy(const CTexture::UID uid);
const VkDescriptorSetLayout& GetDescriptorIndexingSetLayout() const { return m_DescriptorIndexingSetLayout; }
const VkDescriptorSetLayout& GetUniformDescriptorSetLayout() const { return m_UniformDescriptorSetLayout; }
const VkDescriptorSet& GetDescriptorIndexingSet() { return m_DescriptorIndexingSet; }
const std::vector& GetDescriptorSetLayouts() const { return m_DescriptorSetLayouts; }
private:
struct SingleTypePool
{
VkDescriptorSetLayout layout;
VkDescriptorPool pool;
int16_t firstFreeIndex = 0;
- std::vector> elements;
+ static constexpr int16_t INVALID_INDEX = -1;
+ struct Element
+ {
+ VkDescriptorSet set = VK_NULL_HANDLE;
+ uint32_t version = 0;
+ int16_t nextFreeIndex = INVALID_INDEX;
+ };
+ std::vector elements;
};
SingleTypePool& GetSingleTypePool(const VkDescriptorType type, const uint32_t size);
CDevice* m_Device = nullptr;
bool m_UseDescriptorIndexing = false;
VkDescriptorPool m_DescriptorIndexingPool = VK_NULL_HANDLE;
VkDescriptorSet m_DescriptorIndexingSet = VK_NULL_HANDLE;
VkDescriptorSetLayout m_DescriptorIndexingSetLayout = VK_NULL_HANDLE;
VkDescriptorSetLayout m_UniformDescriptorSetLayout = VK_NULL_HANDLE;
std::vector m_DescriptorSetLayouts;
static constexpr uint32_t DESCRIPTOR_INDEXING_BINDING_SIZE = 16384;
static constexpr uint32_t NUMBER_OF_BINDINGS_PER_DESCRIPTOR_INDEXING_SET = 3;
struct DescriptorIndexingBindingMap
{
static_assert(std::numeric_limits::max() >= DESCRIPTOR_INDEXING_BINDING_SIZE);
int16_t firstFreeIndex = 0;
std::vector elements;
std::unordered_map map;
};
std::array
m_DescriptorIndexingBindings;
std::unordered_map m_TextureToBindingMap;
std::unordered_map> m_SingleTypePools;
- std::unordered_map>> m_TextureSingleTypePoolMap;
+ struct SingleTypePoolReference
+ {
+ VkDescriptorType type = VK_DESCRIPTOR_TYPE_MAX_ENUM;
+ uint32_t version = 0;
+ int16_t elementIndex = SingleTypePool::INVALID_INDEX;
+ uint8_t size = 0;
+ };
+ std::unordered_map> m_TextureSingleTypePoolMap;
using SingleTypeCacheKey = std::pair>;
struct SingleTypeCacheKeyHash
{
size_t operator()(const SingleTypeCacheKey& key) const;
};
std::unordered_map m_SingleTypeSets;
+
+ std::unique_ptr m_ErrorTexture;
};
} // namespace Vulkan
} // namespace Backend
} // namespace Renderer
#endif // INCLUDED_RENDERER_BACKEND_VULKAN_DESCRIPTORMANAGER
Index: ps/trunk/source/renderer/backend/vulkan/Texture.h
===================================================================
--- ps/trunk/source/renderer/backend/vulkan/Texture.h (revision 27510)
+++ ps/trunk/source/renderer/backend/vulkan/Texture.h (revision 27511)
@@ -1,132 +1,133 @@
/* Copyright (C) 2023 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_RENDERER_BACKEND_VULKAN_TEXTURE
#define INCLUDED_RENDERER_BACKEND_VULKAN_TEXTURE
#include "renderer/backend/ITexture.h"
#include "renderer/backend/Sampler.h"
#include "renderer/backend/vulkan/VMA.h"
#include
#include
namespace Renderer
{
namespace Backend
{
namespace Vulkan
{
class CDevice;
class CTexture final : public ITexture
{
public:
~CTexture() override;
IDevice* GetDevice() override;
Type GetType() const override { return m_Type; }
uint32_t GetUsage() const override { return m_Usage; }
Format GetFormat() const override { return m_Format; }
uint32_t GetWidth() const override { return m_Width; }
uint32_t GetHeight() const override { return m_Height; }
uint32_t GetMIPLevelCount() const override { return m_MIPLevelCount; }
uint32_t GetSampleCount() const { return m_SampleCount; }
uint32_t GetLayerCount() const { return m_LayerCount; }
VkImage GetImage() { return m_Image; }
VkImageView GetAttachmentImageView() { return m_AttachmentImageView; }
VkImageView GetSamplerImageView() { return m_SamplerImageView; }
VkSampler GetSampler() { return m_Sampler; }
bool IsCompareEnabled() { return m_IsCompareEnabled; }
VkFormat GetVkFormat() const { return m_VkFormat; }
VkImageAspectFlags GetAttachmentImageAspectMask() { return m_AttachmentImageAspectMask; }
VkImageAspectFlags GetSamplerImageAspectMask() { return m_SamplerImageAspectMask; }
bool IsInitialized() const { return m_Initialized; }
void SetInitialized() { m_Initialized = true; }
/**
* @return UID of the texture. It's unique along all textures during a whole
* application run. We assume that 32bits should be enough, else we'd have
* a too big texture flow.
*/
using UID = uint32_t;
+ static constexpr UID INVALID_UID = 0;
UID GetUID() const { return m_UID; }
private:
friend class CDevice;
friend class CSwapChain;
CTexture();
static std::unique_ptr Create(
CDevice* device, const char* name, const Type type, const uint32_t usage,
const Format format, const uint32_t width, const uint32_t height,
const Sampler::Desc& defaultSamplerDesc,
const uint32_t MIPLevelCount, const uint32_t sampleCount);
static std::unique_ptr WrapBackbufferImage(
CDevice* device, const char* name, const VkImage image, const VkFormat format,
const VkImageUsageFlags usage, const uint32_t width, const uint32_t height);
Type m_Type = Type::TEXTURE_2D;
uint32_t m_Usage = 0;
Format m_Format = Format::UNDEFINED;
VkFormat m_VkFormat = VK_FORMAT_UNDEFINED;
uint32_t m_Width = 0;
uint32_t m_Height = 0;
uint32_t m_MIPLevelCount = 0;
uint32_t m_SampleCount = 0;
uint32_t m_LayerCount = 0;
CDevice* m_Device = nullptr;
VkImage m_Image = VK_NULL_HANDLE;
VkImageView m_AttachmentImageView = VK_NULL_HANDLE;
VkImageView m_SamplerImageView = VK_NULL_HANDLE;
VkSampler m_Sampler = VK_NULL_HANDLE;
bool m_IsCompareEnabled = false;
VmaAllocation m_Allocation{};
UID m_UID = 0;
// Sampler image aspect mask is submask of the attachment one. As we can't
// have both VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT for
// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
VkImageAspectFlags m_AttachmentImageAspectMask = 0;
VkImageAspectFlags m_SamplerImageAspectMask = 0;
// We store a flag of all subresources, we don't have to handle them separately.
// It's safe to store the current state while we use a single device command
// context.
bool m_Initialized = false;
};
} // namespace Vulkan
} // namespace Backend
} // namespace Renderer
#endif // INCLUDED_RENDERER_BACKEND_VULKAN_TEXTURE