diff --git a/Application/Chunk.cpp b/Application/Chunk.cpp index 5f02536..0045a9c 100644 --- a/Application/Chunk.cpp +++ b/Application/Chunk.cpp @@ -290,6 +290,7 @@ void Chunk::GenerateMesh() int occ_count = (occ1 ? 1 : 0) + (occ2 ? 1 : 0) + (occ3 ? 1 : 0); float ao = 1.0f - (occ_count * 0.2f); + vertex_color = Scop::Vec4f(Scop::Vec3f(base_color) * ao, 1.0f); } else diff --git a/ScopEngine/Runtime/Includes/Graphics/Actor.h b/ScopEngine/Runtime/Includes/Graphics/Actor.h index 09f5315..edaeb5e 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Actor.h +++ b/ScopEngine/Runtime/Includes/Graphics/Actor.h @@ -14,6 +14,13 @@ namespace Scop { friend Scene; + public: + struct CustomPipeline + { + std::shared_ptr shader; + CPUBuffer data; + }; + public: Actor(); Actor(Model model); diff --git a/ScopEngine/Runtime/Includes/Graphics/Material.h b/ScopEngine/Runtime/Includes/Graphics/Material.h index 47088ee..f7aa192 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Material.h +++ b/ScopEngine/Runtime/Includes/Graphics/Material.h @@ -36,8 +36,8 @@ namespace Scop ~Material() { m_data_buffer.Destroy(); } private: - [[nodiscard]] inline bool IsSetInit() const noexcept { return m_set.IsInit(); } - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return m_set.GetSet(frame_index); } + [[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); } + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); } inline void SetupEventListener() { @@ -49,18 +49,18 @@ namespace Scop EventBus::RegisterListener({ functor, "__ScopMaterial" + std::to_string(reinterpret_cast(this)) }); } - inline void UpdateDescriptorSet(const DescriptorSet& set) + inline void UpdateDescriptorSet(std::shared_ptr set) { - m_set = set.Duplicate(); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType()); } inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) { if(m_have_been_updated_this_frame) return; - m_set.SetImage(frame_index, 0, *m_textures.albedo); - m_set.SetUniformBuffer(frame_index, 1, m_data_buffer.Get(frame_index)); - m_set.Update(frame_index, cmd); + p_set->SetImage(frame_index, 0, *m_textures.albedo); + p_set->SetUniformBuffer(frame_index, 1, m_data_buffer.Get(frame_index)); + p_set->Update(frame_index, cmd); static CPUBuffer buffer(sizeof(MaterialData)); std::memcpy(buffer.GetData(), &m_data, buffer.GetSize()); @@ -73,7 +73,7 @@ namespace Scop UniformBuffer m_data_buffer; MaterialTextures m_textures; MaterialData m_data; - DescriptorSet m_set; + std::shared_ptr p_set; bool m_have_been_updated_this_frame = false; }; } diff --git a/ScopEngine/Runtime/Includes/Graphics/Model.h b/ScopEngine/Runtime/Includes/Graphics/Model.h index a9bff4a..9781458 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Model.h +++ b/ScopEngine/Runtime/Includes/Graphics/Model.h @@ -30,7 +30,7 @@ namespace Scop [[nodiscard]] inline Vec3f GetCenter() const noexcept { return m_center; } [[nodiscard]] inline std::shared_ptr GetMesh() const { return p_mesh; } - void Draw(VkCommandBuffer cmd, const DescriptorSet& matrices_set, const class GraphicPipeline& pipeline, DescriptorSet& set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const; + void Draw(VkCommandBuffer cmd, std::shared_ptr matrices_set, const class GraphicPipeline& pipeline, std::shared_ptr set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const; ~Model() = default; diff --git a/ScopEngine/Runtime/Includes/Graphics/Sprite.h b/ScopEngine/Runtime/Includes/Graphics/Sprite.h index 6b9919f..a881eb4 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Sprite.h +++ b/ScopEngine/Runtime/Includes/Graphics/Sprite.h @@ -37,22 +37,22 @@ namespace Scop ~Sprite(); private: - [[nodiscard]] inline bool IsSetInit() const noexcept { return m_set.IsInit(); } - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return m_set.GetSet(frame_index); } + [[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); } + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); } - inline void UpdateDescriptorSet(const DescriptorSet& set) + inline void UpdateDescriptorSet(std::shared_ptr set) { - m_set = set.Duplicate(); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType()); } inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) { - m_set.SetImage(frame_index, 0, *p_texture); - m_set.Update(frame_index, cmd); + p_set->SetImage(frame_index, 0, *p_texture); + p_set->Update(frame_index, cmd); } private: - DescriptorSet m_set; + std::shared_ptr p_set; std::shared_ptr p_texture; std::shared_ptr p_script; std::shared_ptr p_mesh; diff --git a/ScopEngine/Runtime/Includes/Graphics/Text.h b/ScopEngine/Runtime/Includes/Graphics/Text.h index 056691f..002d5a1 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Text.h +++ b/ScopEngine/Runtime/Includes/Graphics/Text.h @@ -29,20 +29,20 @@ namespace Scop virtual ~Text() = default; private: - [[nodiscard]] inline bool IsSetInit() const noexcept { return m_set.IsInit(); } - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return m_set.GetSet(frame_index); } - inline void UpdateDescriptorSet(const DescriptorSet& set) + [[nodiscard]] inline bool IsSetInit() const noexcept { return p_set && p_set->IsInit(); } + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t frame_index) const noexcept { return p_set->GetSet(frame_index); } + inline void UpdateDescriptorSet(std::shared_ptr set) { - m_set = set.Duplicate(); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(set->GetShaderLayout(), set->GetShaderType()); } inline void Bind(std::size_t frame_index, VkCommandBuffer cmd) { - m_set.SetImage(frame_index, 0, const_cast(p_font->GetTexture())); - m_set.Update(frame_index, cmd); + p_set->SetImage(frame_index, 0, const_cast(p_font->GetTexture())); + p_set->Update(frame_index, cmd); } private: - DescriptorSet m_set; + std::shared_ptr p_set; std::shared_ptr p_mesh; std::shared_ptr p_font; std::string m_text; diff --git a/ScopEngine/Runtime/Includes/Renderer/Descriptor.h b/ScopEngine/Runtime/Includes/Renderer/Descriptor.h index 36bfea9..06a2f07 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Descriptor.h +++ b/ScopEngine/Runtime/Includes/Renderer/Descriptor.h @@ -5,8 +5,8 @@ #include #include -#include #include +#include #include namespace Scop @@ -17,34 +17,76 @@ namespace Scop NonOwningPtr uniform_buffer_ptr; NonOwningPtr image_ptr; VkDescriptorType type; - ShaderType shader_type; std::uint32_t binding; }; - class DescriptorSet + class DescriptorPool { public: - DescriptorSet() { m_set.fill(VK_NULL_HANDLE); } - DescriptorSet(const ShaderSetLayout& layout, VkDescriptorSetLayout vklayout, ShaderType shader_type); + DescriptorPool() = default; + void Init() noexcept; + void Destroy() noexcept; + + std::shared_ptr RequestDescriptorSet(const ShaderSetLayout& layout, ShaderType shader_type); + void ReturnDescriptorSet(std::shared_ptr set); + + [[nodiscard]] inline VkDescriptorPool Get() const noexcept { return m_pool; } + [[nodiscard]] inline std::size_t GetNumberOfSetsAllocated() const noexcept { return m_allocation_count; } + + ~DescriptorPool() = default; + + private: + std::vector> m_free_sets; + std::vector> m_used_sets; + VkDescriptorPool m_pool; + std::size_t m_allocation_count = 0; + }; + + class DescriptorPoolManager + { + public: + DescriptorPoolManager() = default; + + DescriptorPool& GetAvailablePool(); + void Destroy(); + + ~DescriptorPoolManager() = default; + + private: + std::vector m_pools; + }; + + class DescriptorSet : public std::enable_shared_from_this + { + friend DescriptorPool; + + public: void SetImage(std::size_t i, std::uint32_t binding, class Image& image); void SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer); void SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer); void Update(std::size_t i, VkCommandBuffer cmd = VK_NULL_HANDLE) noexcept; - [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t i) const noexcept { return m_set[i]; } - [[nodiscard]] inline DescriptorSet Duplicate() const { return DescriptorSet{ m_set_layout, m_descriptors }; } - [[nodiscard]] inline bool IsInit() const noexcept { return m_set[0] != VK_NULL_HANDLE; } + void ReturnDescriptorSetToPool(); + + [[nodiscard]] inline VkDescriptorSet GetSet(std::size_t i) const noexcept { return m_sets[i]; } + [[nodiscard]] inline bool IsInit() const noexcept { return m_sets[0] != VK_NULL_HANDLE; } + [[nodiscard]] inline VkDescriptorSetLayout GetVulkanLayout() const noexcept { return m_set_layout; } + [[nodiscard]] inline const ShaderSetLayout& GetShaderLayout() const { return m_shader_layout; } + [[nodiscard]] inline ShaderType GetShaderType() const noexcept { return m_shader_type; } ~DescriptorSet() = default; private: - DescriptorSet(VkDescriptorSetLayout layout, const std::vector& descriptors); + DescriptorSet(DescriptorPool& pool, VkDescriptorSetLayout vulkan_layout, const ShaderSetLayout& layout, std::array vulkan_sets, ShaderType shader_type); private: + ShaderSetLayout m_shader_layout; std::vector m_descriptors; - std::array m_set; + std::array m_sets; VkDescriptorSetLayout m_set_layout; + ShaderType m_shader_type; + DescriptorPool& m_pool; }; } diff --git a/ScopEngine/Runtime/Includes/Renderer/Pipelines/Shader.h b/ScopEngine/Runtime/Includes/Renderer/Pipelines/Shader.h index 35f8d7a..1579bea 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Pipelines/Shader.h +++ b/ScopEngine/Runtime/Includes/Renderer/Pipelines/Shader.h @@ -14,6 +14,8 @@ namespace Scop std::vector > binds; ShaderSetLayout(std::vector > b) : binds(std::move(b)) {} + + inline bool operator==(const ShaderSetLayout& rhs) const { return binds == rhs.binds; } }; struct ShaderPushConstantLayout diff --git a/ScopEngine/Runtime/Includes/Renderer/RenderCore.h b/ScopEngine/Runtime/Includes/Renderer/RenderCore.h index 11559ae..dd30262 100644 --- a/ScopEngine/Runtime/Includes/Renderer/RenderCore.h +++ b/ScopEngine/Runtime/Includes/Renderer/RenderCore.h @@ -35,6 +35,7 @@ namespace Scop [[nodiscard]] inline VkPhysicalDevice GetPhysicalDevice() const noexcept { return m_physical_device; } [[nodiscard]] inline DeviceAllocator& GetAllocator() noexcept { return m_allocator; } [[nodiscard]] inline bool StackSubmits() const noexcept { return m_stack_submits; } + [[nodiscard]] inline class DescriptorPoolManager& GetDescriptorPoolManager() noexcept { return *p_descriptor_pool_manager; } [[nodiscard]] inline std::shared_ptr GetDefaultVertexShader() const { return m_internal_shaders[DEFAULT_VERTEX_SHADER_ID]; } [[nodiscard]] inline std::shared_ptr GetBasicFragmentShader() const { return m_internal_shaders[BASIC_FRAGMENT_SHADER_ID]; } @@ -71,6 +72,7 @@ namespace Scop VkInstance m_instance = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE; VkPhysicalDevice m_physical_device = VK_NULL_HANDLE; + std::unique_ptr p_descriptor_pool_manager; bool m_stack_submits = false; }; } diff --git a/ScopEngine/Runtime/Sources/Graphics/Model.cpp b/ScopEngine/Runtime/Sources/Graphics/Model.cpp index 88199d3..53d4c12 100644 --- a/ScopEngine/Runtime/Sources/Graphics/Model.cpp +++ b/ScopEngine/Runtime/Sources/Graphics/Model.cpp @@ -25,7 +25,7 @@ namespace Scop m_materials.back() = s_default_material; } - void Model::Draw(VkCommandBuffer cmd, const DescriptorSet& matrices_set, const GraphicPipeline& pipeline, DescriptorSet& set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const + void Model::Draw(VkCommandBuffer cmd, std::shared_ptr matrices_set, const GraphicPipeline& pipeline, std::shared_ptr set, std::size_t& drawcalls, std::size_t& polygondrawn, std::size_t frame_index) const { if(!p_mesh) return; @@ -39,7 +39,7 @@ namespace Scop if(!material->IsSetInit()) material->UpdateDescriptorSet(set); material->Bind(frame_index, cmd); - std::array sets = { matrices_set.GetSet(frame_index), material->GetSet(frame_index) }; + std::array sets = { matrices_set->GetSet(frame_index), material->GetSet(frame_index) }; RenderCore::Get().vkCmdBindDescriptorSets(cmd, pipeline.GetPipelineBindPoint(), pipeline.GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); p_mesh->Draw(cmd, drawcalls, polygondrawn, i); } diff --git a/ScopEngine/Runtime/Sources/Graphics/Scene.cpp b/ScopEngine/Runtime/Sources/Graphics/Scene.cpp index f85af8f..babe688 100644 --- a/ScopEngine/Runtime/Sources/Graphics/Scene.cpp +++ b/ScopEngine/Runtime/Sources/Graphics/Scene.cpp @@ -165,7 +165,7 @@ namespace Scop if(m_descriptor.post_process_shader) { - m_post_process.set = std::make_shared(m_descriptor.post_process_shader->GetShaderLayout().set_layouts[0].second, m_descriptor.post_process_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + m_post_process.set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(m_descriptor.post_process_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); m_post_process.data_buffer = std::make_shared(); m_post_process.data_buffer->Init(m_descriptor.post_process_data_size, m_name + "_post_process_data_buffer"); } @@ -178,13 +178,13 @@ namespace Scop m_forward.matrices_buffer = std::make_shared(); m_forward.matrices_buffer->Init(sizeof(ViewerData), m_name + "_matrice_buffer"); - m_forward.matrices_set = std::make_shared(vertex_shader->GetShaderLayout().set_layouts[0].second, vertex_shader->GetPipelineLayout().set_layouts[0], ShaderType::Vertex); + m_forward.matrices_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(vertex_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Vertex); for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { m_forward.matrices_set->SetUniformBuffer(i, 0, m_forward.matrices_buffer->Get(i)); m_forward.matrices_set->Update(i); } - m_forward.albedo_set = std::make_shared(m_descriptor.fragment_shader->GetShaderLayout().set_layouts[0].second, m_descriptor.fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + m_forward.albedo_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(m_descriptor.fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); for(auto& child : m_scene_children) child.Init(renderer); diff --git a/ScopEngine/Runtime/Sources/Renderer/Descriptor.cpp b/ScopEngine/Runtime/Sources/Renderer/Descriptor.cpp index 3c0e138..e0d4421 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Descriptor.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Descriptor.cpp @@ -5,11 +5,14 @@ #include #include #include +#include #include #include namespace Scop { + constexpr std::size_t MAX_SETS_PER_POOL = MAX_FRAMES_IN_FLIGHT * 1024; + void TransitionImageToCorrectLayout(Image& image, VkCommandBuffer cmd) { if(!image.IsInit()) @@ -22,30 +25,144 @@ namespace Scop Error("Vulkan: cannot transition descriptor image layout, unkown image type"); } - DescriptorSet::DescriptorSet(const ShaderSetLayout& layout, VkDescriptorSetLayout vklayout, ShaderType shader_type) - : m_set_layout(vklayout) + void DescriptorPool::Init() noexcept + { + VkDescriptorPoolSize pool_sizes[] = { + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_SETS_PER_POOL }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, MAX_SETS_PER_POOL }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MAX_SETS_PER_POOL } + }; + + VkDescriptorPoolCreateInfo pool_info{}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.poolSizeCount = sizeof(pool_sizes) / sizeof(pool_sizes[0]); + pool_info.pPoolSizes = pool_sizes; + pool_info.maxSets = MAX_SETS_PER_POOL; + pool_info.flags = 0; + kvfCheckVk(RenderCore::Get().vkCreateDescriptorPool(RenderCore::Get().GetDevice(), &pool_info, nullptr, &m_pool)); + m_allocation_count = 0; + } + + void DescriptorPool::Destroy() noexcept + { + if(m_pool == VK_NULL_HANDLE) + return; + for(auto& set : m_free_sets) + kvfDestroyDescriptorSetLayout(RenderCore::Get().GetDevice(), set->m_set_layout); + for(auto& set : m_used_sets) + kvfDestroyDescriptorSetLayout(RenderCore::Get().GetDevice(), set->m_set_layout); + RenderCore::Get().vkDestroyDescriptorPool(RenderCore::Get().GetDevice(), m_pool, nullptr); + m_pool = VK_NULL_HANDLE; + m_allocation_count = 0; + m_free_sets.clear(); + m_used_sets.clear(); + } + + std::shared_ptr DescriptorPool::RequestDescriptorSet(const ShaderSetLayout& layout, ShaderType shader_type) + { + auto it = std::find_if(m_free_sets.begin(), m_free_sets.end(), [&](std::shared_ptr set) + { + return shader_type == set->GetShaderType() && layout == set->GetShaderLayout(); + }); + if(it != m_free_sets.end()) + { + std::shared_ptr set = *it; + m_free_sets.erase(it); + m_used_sets.push_back(set); + return set; + } + + std::array vulkan_sets; + + VkShaderStageFlagBits vulkan_shader_stage; + switch(shader_type) + { + case ShaderType::Vertex: vulkan_shader_stage = VK_SHADER_STAGE_VERTEX_BIT; break; + case ShaderType::Fragment: vulkan_shader_stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; + + default: FatalError("wtf"); vulkan_shader_stage = VK_SHADER_STAGE_VERTEX_BIT; /* Just to shut up warnings */ break; + } + + std::vector bindings(layout.binds.size()); + for(std::size_t i = 0; i < layout.binds.size(); i++) + { + bindings[i].binding = layout.binds[i].first; + bindings[i].descriptorCount = 1; + bindings[i].descriptorType = layout.binds[i].second; + bindings[i].pImmutableSamplers = nullptr; + bindings[i].stageFlags = vulkan_shader_stage; + } + VkDescriptorSetLayout vulkan_layout = kvfCreateDescriptorSetLayout(RenderCore::Get().GetDevice(), bindings.data(), bindings.size()); + + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = m_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &vulkan_layout; + VkDescriptorSet vulkan_set; + kvfCheckVk(RenderCore::Get().vkAllocateDescriptorSets(RenderCore::Get().GetDevice(), &alloc_info, &vulkan_set)); + m_allocation_count++; + vulkan_sets[i] = vulkan_set; + } + + std::shared_ptr set(new DescriptorSet(*this, vulkan_layout, layout, std::move(vulkan_sets), shader_type)); + m_used_sets.push_back(set); + return set; + } + + void DescriptorPool::ReturnDescriptorSet(std::shared_ptr set) + { + //std::size_t i = 0; + auto it = std::find_if(m_used_sets.begin(), m_used_sets.end(), [&](const std::shared_ptr& rhs_set) + { + //i++; + //std::cout << m_used_sets.size() << " " << i << std::endl; + return set == rhs_set; + }); + if(it == m_used_sets.end()) + return; + m_used_sets.erase(it); + m_free_sets.push_back(set); + } + + DescriptorPool& DescriptorPoolManager::GetAvailablePool() + { + for(auto& pool : m_pools) + { + if(pool.GetNumberOfSetsAllocated() < MAX_SETS_PER_POOL) + return pool; + } + m_pools.emplace_back().Init(); + return m_pools.back(); + } + + void DescriptorPoolManager::Destroy() + { + for(auto& pool : m_pools) + pool.Destroy(); + m_pools.clear(); + } + + DescriptorSet::DescriptorSet(DescriptorPool& pool, VkDescriptorSetLayout vulkan_layout, const ShaderSetLayout& layout, std::array vulkan_sets, ShaderType shader_type) : + m_shader_layout(layout), + m_sets(std::move(vulkan_sets)), + m_set_layout(vulkan_layout), + m_shader_type(shader_type), + m_pool(pool) { for(auto& [binding, type] : layout.binds) { m_descriptors.emplace_back(); m_descriptors.back().type = type; - m_descriptors.back().shader_type = shader_type; m_descriptors.back().binding = binding; } - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - m_set[i] = kvfAllocateDescriptorSet(RenderCore::Get().GetDevice(), vklayout); - } - - DescriptorSet::DescriptorSet(VkDescriptorSetLayout layout, const std::vector& descriptors) - : m_set_layout(layout), m_descriptors(descriptors) - { - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - m_set[i] = kvfAllocateDescriptorSet(RenderCore::Get().GetDevice(), layout); } void DescriptorSet::SetImage(std::size_t i, std::uint32_t binding, class Image& image) { - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -65,7 +182,7 @@ namespace Scop void DescriptorSet::SetStorageBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer) { - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -85,7 +202,7 @@ namespace Scop void DescriptorSet::SetUniformBuffer(std::size_t i, std::uint32_t binding, class GPUBuffer& buffer) { - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); auto it = std::find_if(m_descriptors.begin(), m_descriptors.end(), [=](Descriptor descriptor) { return binding == descriptor.binding; @@ -105,7 +222,7 @@ namespace Scop void DescriptorSet::Update(std::size_t i, VkCommandBuffer cmd) noexcept { - Verify(m_set[i] != VK_NULL_HANDLE, "invalid descriptor"); + Verify(m_sets[i] != VK_NULL_HANDLE, "invalid descriptor"); std::size_t image_count = 0; std::size_t buffer_count = 0; @@ -137,7 +254,7 @@ namespace Scop info.imageLayout = descriptor.image_ptr->GetLayout(); info.imageView = descriptor.image_ptr->GetImageView(); image_infos[image_index] = std::move(info); - writes[write_index] = kvfWriteImageToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &image_infos[image_index], descriptor.binding); + writes[write_index] = kvfWriteImageToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &image_infos[image_index], descriptor.binding); image_index++; } else if(descriptor.uniform_buffer_ptr) @@ -147,7 +264,7 @@ namespace Scop info.offset = descriptor.uniform_buffer_ptr->GetOffset(); info.range = VK_WHOLE_SIZE; buffer_infos[buffer_index] = std::move(info); - writes[write_index] = kvfWriteUniformBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &buffer_infos[buffer_index], descriptor.binding); + writes[write_index] = kvfWriteUniformBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &buffer_infos[buffer_index], descriptor.binding); buffer_index++; } else if(descriptor.storage_buffer_ptr) @@ -157,11 +274,16 @@ namespace Scop info.offset = descriptor.storage_buffer_ptr->GetOffset(); info.range = VK_WHOLE_SIZE; buffer_infos[buffer_index] = std::move(info); - writes[write_index] = kvfWriteStorageBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_set[i], &buffer_infos[buffer_index], descriptor.binding); + writes[write_index] = kvfWriteStorageBufferToDescriptorSet(RenderCore::Get().GetDevice(), m_sets[i], &buffer_infos[buffer_index], descriptor.binding); buffer_index++; } write_index++; } RenderCore::Get().vkUpdateDescriptorSets(RenderCore::Get().GetDevice(), writes.size(), writes.data(), 0, nullptr); } + + void DescriptorSet::ReturnDescriptorSetToPool() + { + m_pool.ReturnDescriptorSet(shared_from_this()); + } } diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderCore.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderCore.cpp index 2b5804d..c5b3deb 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderCore.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderCore.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -120,6 +121,8 @@ namespace Scop m_allocator.AttachToDevice(m_device, m_physical_device); + p_descriptor_pool_manager = std::make_unique(); + ShaderLayout vertex_shader_layout( { { 0, @@ -258,6 +261,8 @@ namespace Scop if(s_instance == nullptr) return; WaitDeviceIdle(); + p_descriptor_pool_manager->Destroy(); + p_descriptor_pool_manager.reset(); m_allocator.DetachFromDevice(); for(auto shader: m_internal_shaders) shader->Destroy(); diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/2DPass.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/2DPass.cpp index 704ad17..1e5c594 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/2DPass.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/2DPass.cpp @@ -49,8 +49,8 @@ namespace Scop }; EventBus::RegisterListener({ functor, "__ScopRender2DPass" }); - p_viewer_data_set = std::make_shared(p_vertex_shader->GetShaderLayout().set_layouts[0].second, p_vertex_shader->GetPipelineLayout().set_layouts[0], ShaderType::Vertex); - p_texture_set = std::make_shared(p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + p_viewer_data_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_vertex_shader->GetShaderLayout().set_layouts[0].second,ShaderType::Vertex); + p_texture_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); p_viewer_data_buffer = std::make_shared(); p_viewer_data_buffer->Init(sizeof(ViewerData2D)); @@ -91,7 +91,7 @@ namespace Scop sprite_data.position = Vec2f{ static_cast(sprite.GetPosition().x), static_cast(sprite.GetPosition().y) }; sprite_data.color = sprite.GetColor(); if(!sprite.IsSetInit()) - const_cast(sprite).UpdateDescriptorSet(*p_texture_set); + const_cast(sprite).UpdateDescriptorSet(p_texture_set); const_cast(sprite).Bind(frame_index, cmd); std::array sets = { p_viewer_data_set->GetSet(frame_index), sprite.GetSet(frame_index) }; RenderCore::Get().vkCmdBindDescriptorSets(cmd, m_pipeline.GetPipelineBindPoint(), m_pipeline.GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); @@ -104,7 +104,7 @@ namespace Scop sprite_data.position = Vec2f{ static_cast(text.GetPosition().x), static_cast(text.GetPosition().y) }; sprite_data.color = text.GetColor(); if(!text.IsSetInit()) - const_cast(text).UpdateDescriptorSet(*p_texture_set); + const_cast(text).UpdateDescriptorSet(p_texture_set); const_cast(text).Bind(frame_index, cmd); std::array sets = { p_viewer_data_set->GetSet(frame_index), text.GetSet(frame_index) }; RenderCore::Get().vkCmdBindDescriptorSets(cmd, m_pipeline.GetPipelineBindPoint(), m_pipeline.GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/FinalPass.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/FinalPass.cpp index 80c72d9..a11d942 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/FinalPass.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/FinalPass.cpp @@ -31,7 +31,7 @@ namespace Scop }; EventBus::RegisterListener({ functor, "__ScopFinalPass" }); - p_set = std::make_shared(p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); } void FinalPass::Pass(Scene& scene, Renderer& renderer, Texture& render_target) diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/ForwardPass.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/ForwardPass.cpp index bc0692d..b36d378 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/ForwardPass.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/ForwardPass.cpp @@ -65,7 +65,7 @@ namespace Scop { auto model_data = setup_model(actor); RenderCore::Get().vkCmdPushConstants(cmd, pipeline.GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ModelData), &model_data); - actor.GetModel().Draw(cmd, *data.matrices_set, pipeline, *data.albedo_set, renderer.GetDrawCallsCounterRef(), renderer.GetPolygonDrawnCounterRef(), renderer.GetCurrentFrameIndex()); + actor.GetModel().Draw(cmd, data.matrices_set, pipeline, data.albedo_set, renderer.GetDrawCallsCounterRef(), renderer.GetPolygonDrawnCounterRef(), renderer.GetCurrentFrameIndex()); } else { @@ -79,7 +79,7 @@ namespace Scop continue; auto model_data = setup_model(it->second); RenderCore::Get().vkCmdPushConstants(cmd, pipeline.GetPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ModelData), &model_data); - it->second.GetModel().Draw(cmd, *data.matrices_set, pipeline, *data.albedo_set, renderer.GetDrawCallsCounterRef(), renderer.GetPolygonDrawnCounterRef(), renderer.GetCurrentFrameIndex()); + it->second.GetModel().Draw(cmd, data.matrices_set, pipeline, data.albedo_set, renderer.GetDrawCallsCounterRef(), renderer.GetPolygonDrawnCounterRef(), renderer.GetCurrentFrameIndex()); } pipeline.EndPipeline(cmd); } diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/SkyboxPass.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/SkyboxPass.cpp index 2183577..c80d2a9 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/SkyboxPass.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/SkyboxPass.cpp @@ -40,7 +40,7 @@ namespace Scop EventBus::RegisterListener({ functor, "__ScopSkyboxPass" }); m_cube = CreateCube(); - p_set = std::make_shared(p_fragment_shader->GetShaderLayout().set_layouts[0].second, p_fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); + p_set = RenderCore::Get().GetDescriptorPoolManager().GetAvailablePool().RequestDescriptorSet(p_fragment_shader->GetShaderLayout().set_layouts[0].second, ShaderType::Fragment); } void SkyboxPass::Pass(Scene& scene, Renderer& renderer, class Texture& render_target) diff --git a/ScopEngine/ThirdParty/KVF/kvf.h b/ScopEngine/ThirdParty/KVF/kvf.h index df2d36d..1308495 100755 --- a/ScopEngine/ThirdParty/KVF/kvf.h +++ b/ScopEngine/ThirdParty/KVF/kvf.h @@ -374,12 +374,12 @@ void kvfCheckVk(VkResult result); #ifdef KVF_DESCRIPTOR_POOL_CAPACITY #undef KVF_DESCRIPTOR_POOL_CAPACITY #endif -#define KVF_DESCRIPTOR_POOL_CAPACITY 512 +#define KVF_DESCRIPTOR_POOL_CAPACITY 1024 #ifdef KVF_COMMAND_POOL_CAPACITY #undef KVF_COMMAND_POOL_CAPACITY #endif -#define KVF_COMMAND_POOL_CAPACITY 512 +#define KVF_COMMAND_POOL_CAPACITY 1024 typedef struct {