From 4ccfd399af1d1936c2c04eb2a8d635327b7edd63 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Tue, 13 Sep 2022 19:46:51 +0800 Subject: [PATCH] Renderpass execution and descriptor set writes --- SHADE_Engine/SHADE_Engine.vcxproj | 4 +- SHADE_Engine/SHADE_Engine.vcxproj.filters | 2 + .../Editor/Backend/SHImGuiVulkanBackend.cpp | 28 +++- .../src/Editor/Backend/SHImGuiVulkanBackend.h | 5 +- .../Graphics/Commands/SHVkCommandBuffer.cpp | 5 + .../src/Graphics/Commands/SHVkCommandBuffer.h | 4 +- .../Descriptors/SHDescriptorSetUpdater.cpp | 84 +++++++++++ .../Descriptors/SHDescriptorSetUpdater.h | 60 ++++++++ .../Descriptors/SHVkDescriptorSetGroup.cpp | 107 +++++++++++++- .../Descriptors/SHVkDescriptorSetGroup.h | 132 ++++++++++-------- .../Descriptors/SHVkDescriptorSetLayout.cpp | 5 + .../Descriptors/SHVkDescriptorSetLayout.h | 1 + .../Graphics/Devices/SHVkLogicalDevice.cpp | 16 +++ .../src/Graphics/Devices/SHVkLogicalDevice.h | 3 + .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 2 - .../Graphics/RenderGraph/SHRenderGraph.cpp | 86 +++++++++++- .../src/Graphics/RenderGraph/SHRenderGraph.h | 51 ++++++- .../Graphics/Shaders/SHShaderReflected.cpp | 2 +- .../src/Graphics/Shaders/SHShaderReflected.h | 5 +- 19 files changed, 515 insertions(+), 87 deletions(-) create mode 100644 SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp create mode 100644 SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h diff --git a/SHADE_Engine/SHADE_Engine.vcxproj b/SHADE_Engine/SHADE_Engine.vcxproj index c8dbf732..08f58da4 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj +++ b/SHADE_Engine/SHADE_Engine.vcxproj @@ -128,6 +128,7 @@ + @@ -206,6 +207,7 @@ + @@ -276,4 +278,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/SHADE_Engine/SHADE_Engine.vcxproj.filters b/SHADE_Engine/SHADE_Engine.vcxproj.filters index 1324473d..8e6c7d90 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj.filters +++ b/SHADE_Engine/SHADE_Engine.vcxproj.filters @@ -367,6 +367,7 @@ Tools + @@ -550,5 +551,6 @@ Tools + \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.cpp b/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.cpp index f00a2072..1ec09e05 100644 --- a/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.cpp +++ b/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.cpp @@ -40,7 +40,7 @@ namespace SHADE gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1); } */ - static uint32_t __glsl_shader_vert_spv[] = + static std::vector __glsl_shader_vert_spv = { 0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, @@ -97,7 +97,7 @@ namespace SHADE fColor = In.Color * texture(sTexture, In.UV.st); } */ - static uint32_t __glsl_shader_frag_spv[] = + static std::vector __glsl_shader_frag_spv = { 0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, @@ -137,7 +137,7 @@ namespace SHADE std::array translate; }; - void SHImGuiVulkanBackend::CreateInstance(Handle const& logicalDevice) noexcept + void SHImGuiVulkanBackend::CreateInstance(Handle const& logicalDevice, Handle const& renderpass, uint32_t subpassIndex) noexcept { if (ImGui::GetCurrentContext() == nullptr) { @@ -189,7 +189,7 @@ namespace SHADE //Initialize instance auto instance = std::make_unique(); - instance->InitializePipeline(io); + instance->InitializePipeline(io, renderpass, subpassIndex); instance->lastFrameTime = std::chrono::high_resolution_clock::now(); io.UserData = instance.release(); @@ -303,7 +303,7 @@ namespace SHADE io.Fonts->TexID = nullptr; } - void SHImGuiVulkanBackend::SHBreachInstance::InitializePipeline(ImGuiIO& io) noexcept + void SHImGuiVulkanBackend::SHBreachInstance::InitializePipeline(ImGuiIO& io, Handle const& renderpass, uint32_t subpassIndex) noexcept { SHVertexInputState vInputState{}; vInputState.AddBinding(false, true, @@ -314,7 +314,23 @@ namespace SHADE } ); - //Handle newPipeline = device->CreatePipeline() + Handle vs = device->CreateShaderModule(__glsl_shader_vert_spv, "main", vk::ShaderStageFlagBits::eVertex, "__glsl_shader_vert_spv"); + Handle fs = device->CreateShaderModule(__glsl_shader_frag_spv, "main", vk::ShaderStageFlagBits::eFragment, "__glsl_shader_frag_spv"); + + SHPipelineLayoutParams pipelineLayoutParams + { + .shaderModules = std::move (std::vector> + { + vs, + fs, + }), + }; + + Handle pipelineLayouot = device->CreatePipelineLayout(pipelineLayoutParams); + Handle newPipeline = device->CreatePipeline(pipelineLayouot, nullptr, renderpass, subpassIndex, SH_PIPELINE_TYPE::GRAPHICS); + newPipeline->GetPipelineState().SetVertexInputState(vInputState); + newPipeline->ConstructPipeline(); + } } \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.h b/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.h index 387d173d..d6ebf84d 100644 --- a/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.h +++ b/SHADE_Engine/src/Editor/Backend/SHImGuiVulkanBackend.h @@ -41,11 +41,10 @@ namespace SHADE std::vector fontsMipOffset; public: void CreateFontsTexture (Handle image, ImGuiIO& io) noexcept; - void InitializeRenderpass (void) noexcept; - void InitializePipeline(ImGuiIO& io) noexcept; + void InitializePipeline(ImGuiIO& io, Handle const& renderpass, uint32_t subpassIndex) noexcept; }; public: - static void CreateInstance(Handle const& logicalDevice) noexcept; + static void CreateInstance(Handle const& logicalDevice, Handle const& renderpass, uint32_t subpassIndex) noexcept; static void Render(void) noexcept; diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 0cc9138e..5b2d15fe 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -202,6 +202,11 @@ namespace SHADE vkCommandBuffer.endRenderPass(); } + void SHVkCommandBuffer::NextSubpass(void) noexcept + { + vkCommandBuffer.nextSubpass(commandBufferType == SH_CMD_BUFFER_TYPE::PRIMARY ? vk::SubpassContents::eInline : vk::SubpassContents::eSecondaryCommandBuffers); + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index 932a0d47..d2171c25 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h @@ -96,11 +96,12 @@ namespace SHADE /*-----------------------------------------------------------------------*/ void Reset(void); - // Begins and Ends + // Begins, Ends and Nexts void BeginRecording (void) noexcept; void EndRecording (void) noexcept; void BeginRenderpass (Handle const& renderpassHdl, Handle const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept; void EndRenderpass (void) noexcept; + void NextSubpass (void) noexcept; // Dynamic State void SetviewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept; @@ -124,6 +125,7 @@ namespace SHADE std::vector const& imageMemoryBarriers ) const noexcept; + // Push Constant variable setting template void SetPushConstantVariable(std::string variableName, T const& data) noexcept diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp new file mode 100644 index 00000000..a1b1cbc2 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp @@ -0,0 +1,84 @@ +#include "SHpch.h" +#include "SHDescriptorSetUpdater.h" + +namespace SHADE +{ + + SHDescriptorWriteInfo::SHDescriptorWriteInfo(SHDescriptorWriteInfo&& rhs) noexcept + : descImageInfos{ std::move(rhs.descImageInfos) } + , descBufferInfos{ std::move(rhs.descBufferInfos) } + , descTexelBufferInfos{std::move (rhs.descTexelBufferInfos)} + { + + } + + SHDescriptorWriteInfo::SHDescriptorWriteInfo(void) noexcept + : descImageInfos{} + , descBufferInfos{} + , descTexelBufferInfos{} + { + + } + + /***************************************************************************/ + /*! + + \brief + Links the write infos to the vulkan write descriptor sets. + + */ + /***************************************************************************/ + void SHDescriptorSetUpdater::LinkInfoToWriteDescSet(void) noexcept + { + for (uint32_t i = 0; i < writeInfos.size(); ++i) + { + writeDescSets[i].pImageInfo = writeInfos[i].descImageInfos.data(); + writeDescSets[i].pBufferInfo = writeInfos[i].descBufferInfos.data(); + writeDescSets[i].pTexelBufferView = writeInfos[i].descTexelBufferInfos.data(); + } + } + + SHDescriptorWriteInfo& SHDescriptorWriteInfo::operator=(SHDescriptorWriteInfo&& rhs) noexcept + { + if (&rhs == this) + return *this; + + descImageInfos = std::move(rhs.descImageInfos); + descBufferInfos = std::move(rhs.descBufferInfos); + descTexelBufferInfos = std::move(rhs.descTexelBufferInfos); + + return *this; + } + + + SHDescriptorSetUpdater::SHDescriptorSetUpdater(SHDescriptorSetUpdater&& rhs) noexcept + : writeInfos{ std::move(rhs.writeInfos) } + , writeHashMap {std::move (rhs.writeHashMap)} + { + + } + + SHDescriptorSetUpdater::SHDescriptorSetUpdater(void) noexcept + : writeInfos{} + , writeHashMap{} + { + + } + + std::vector const& SHDescriptorSetUpdater::GetWriteDescriptorSets(void) const noexcept + { + return writeDescSets; + } + + SHDescriptorSetUpdater& SHDescriptorSetUpdater::operator=(SHDescriptorSetUpdater&& rhs) noexcept + { + if (&rhs == this) + return *this; + + writeInfos = std::move (rhs.writeInfos); + writeHashMap = std::move (rhs.writeHashMap); + + return *this; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h new file mode 100644 index 00000000..7a5ae967 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include "Graphics/SHVulkanIncludes.h" +#include "Graphics/Shaders/SHShaderReflected.h" + +namespace SHADE +{ + // Vulkan doesn't use all of the information when looking at a writeDescriptorSet. It all + // depends on the descriptor type. This struct plays it safe by having members that would + // accommodate all types of descriptors. + class SHDescriptorWriteInfo + { + //! When we want to update a descriptor that is an image, it goes in here + std::vector descImageInfos; + + //! When we want to update a descriptor that is a buffer, it goes in here + std::vector descBufferInfos; + + //! When we want to update a descriptor that is an texel buffer, it goes in here + std::vector descTexelBufferInfos; + + public: + SHDescriptorWriteInfo (void) noexcept; + SHDescriptorWriteInfo (SHDescriptorWriteInfo&& rhs) noexcept; + SHDescriptorWriteInfo& operator= (SHDescriptorWriteInfo&& rhs) noexcept; + + friend class SHVkDescriptorSetGroup; + friend class SHDescriptorSetUpdater; + }; + + class SHDescriptorSetUpdater + { + private: + //! When we want to update descriptor sets, this will get passed into vkUpdateDescriptorSets. + //! Each write will correspond to a binding from a set. If the binding is a variable + //! sized binding, pImageInfo (e.g.) will point to an array of vk::DescriptorImageInfo. + std::vector writeInfos; + + //! When we want to update a write, we need to use this to identify the index of the write. + std::unordered_map writeHashMap; + + //! We keep this here because we want this to be immediately passable to vkUpdateDescriptorSets + std::vector writeDescSets; + + void LinkInfoToWriteDescSet(void) noexcept; + + public: + SHDescriptorSetUpdater (void) noexcept; + SHDescriptorSetUpdater(SHDescriptorSetUpdater&& rhs) noexcept; + SHDescriptorSetUpdater& operator= (SHDescriptorSetUpdater&& rhs) noexcept; + + public: + std::vector const& GetWriteDescriptorSets (void) const noexcept; + + friend class SHVkDescriptorSetGroup; + }; +} + diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp index 6bdc5601..16143aa5 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp @@ -42,9 +42,11 @@ namespace SHADE { // Create the layout for each concurrent frame std::vector vkLayouts{ layouts.size() }; - for (auto& layout : layouts) + + //for (auto& layout : layouts) + for (uint32_t i = 0; i < layouts.size(); ++i) { - vkLayouts.push_back(layout->GetVkHandle()); + vkLayouts.push_back(layouts[i]->GetVkHandle()); } // Check for variable descriptor count @@ -67,6 +69,66 @@ namespace SHADE // allocate descriptor sets descSets = device->GetVkLogicalDevice().allocateDescriptorSets(DESC_SET_LAYOUT_CREATE_INFO); + + + + // Now we want to prepare the write descriptor sets for writing later. + for (uint32_t i = 0; i < layouts.size(); ++i) + { + auto const& bindings = layouts[i]->GetBindings(); + for (auto& binding : bindings) + { + BindingAndSetHash writeHash = binding.BindPoint; + writeHash |= static_cast(i) << 32; + + // new write for the binding + updater.writeInfos.emplace_back(); + updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); + auto& writeInfo = updater.writeInfos.back(); + + updater.writeDescSets.emplace_back(); + auto& writeDescSet = updater.writeDescSets.back(); + + // Initialize info for write + writeDescSet.descriptorType = binding.Type; + writeDescSet.dstArrayElement = 0; + writeDescSet.dstSet = descSets[i]; + writeDescSet.dstBinding = binding.BindPoint; + + // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in + uint32_t descriptorCount = (binding.flags & vk::DescriptorBindingFlagBits::eVariableDescriptorCount) ? variableDescCounts[i] : 1; + writeDescSet.descriptorCount = descriptorCount; + + switch (binding.Type) + { + //case vk::DescriptorType::eSampler: + //case vk::DescriptorType::eSampledImage: + case vk::DescriptorType::eCombinedImageSampler: + writeInfo.descImageInfos.resize(descriptorCount); + break; + //case vk::DescriptorType::eStorageImage: + // break; + case vk::DescriptorType::eUniformTexelBuffer: + case vk::DescriptorType::eStorageTexelBuffer: + case vk::DescriptorType::eUniformBuffer: + case vk::DescriptorType::eStorageBuffer: + writeInfo.descImageInfos.resize (descriptorCount); + break; + //case vk::DescriptorType::eUniformBufferDynamic: + // break; + //case vk::DescriptorType::eStorageBufferDynamic: + // break; + //case vk::DescriptorType::eInputAttachment: + // break; + //case vk::DescriptorType::eInlineUniformBlock: + // break; + default: + break; + } + } + } + // Link all the writeDescSet data for vkUpdateDescriptorSets to write to the linked descriptors + updater.LinkInfoToWriteDescSet(); } /***************************************************************************/ @@ -82,4 +144,45 @@ namespace SHADE if (!descSets.empty()) device->GetVkLogicalDevice().freeDescriptorSets(descPool->GetVkHandle(), descSets); } + + /***************************************************************************/ + /*! + + \brief + Modifies a descriptor write info. #NoteToSelf: This function does NOT + need to modify the writeDescSets. Those are already linked before. + + \param imageViewsAndSamplers + Image and view samplers + + */ + /***************************************************************************/ + void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept + { + // Find the target writeDescSet + BindingAndSetHash writeHash = binding; + writeHash |= static_cast(set) << 32; + auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)]; + + if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) + { + SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); + } + + for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) + { + // write sampler and image view + auto& ivs = imageViewsAndSamplers[i]; + writeInfo.descImageInfos[i].imageView = ivs.first; + writeInfo.descImageInfos[i].sampler = ivs.second; + } + } + + + void SHVkDescriptorSetGroup::UpdateDescriptorSet(void) noexcept + { + device->UpdateDescriptorSets(updater.GetWriteDescriptorSets()); + } + + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h index b95859bb..9e311e9a 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h @@ -1,71 +1,89 @@ - #pragma once +#pragma once // Project Includes #include "Graphics/SHVulkanIncludes.h" #include "Resource/Handle.h" +#include "Graphics/Shaders/SHShaderReflected.h" +#include "SHDescriptorSetUpdater.h" namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Forward Declarations */ - /*---------------------------------------------------------------------------------*/ - class SHVkLogicalDevice; - class SHVkDescriptorPool; - class SHVkDescriptorSetLayout; + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetLayout; - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /// + /// + /// + class SHVkDescriptorSetGroup + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructor/Destructors */ + /*-----------------------------------------------------------------------------*/ /// - /// + /// Constructs a Descriptor Set with the specified layout using the specified + /// pool meant for use with the specified surface. This Set will be created with + /// multiple Vulkan Descriptor Set objects based on the max number of concurrent + /// frames for the specified surface. /// - class SHVkDescriptorSetGroup - { - public: - /*-----------------------------------------------------------------------------*/ - /* Constructor/Destructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Constructs a Descriptor Set with the specified layout using the specified - /// pool meant for use with the specified surface. This Set will be created with - /// multiple Vulkan Descriptor Set objects based on the max number of concurrent - /// frames for the specified surface. - /// - /// Vulkan logical device used to create the Set. - /// Descriptor Pool used to create the Set. - /// Descriptor Set Layout to create the Set with. - SHVkDescriptorSetGroup(Handle deviceHdl, Handle pool, - std::vector> const& layouts, - std::vector const& variableDescCounts); - SHVkDescriptorSetGroup(const SHVkDescriptorSetGroup&) = delete; - SHVkDescriptorSetGroup(SHVkDescriptorSetGroup&& rhs) noexcept = default; - /// - /// Destructor which will unload and deallocate all resources for this Descriptor Set. - /// - ~SHVkDescriptorSetGroup() noexcept; + /// Vulkan logical device used to create the Set. + /// Descriptor Pool used to create the Set. + /// Descriptor Set Layout to create the Set with. + SHVkDescriptorSetGroup(Handle deviceHdl, Handle pool, + std::vector> const& layouts, + std::vector const& variableDescCounts); + SHVkDescriptorSetGroup(const SHVkDescriptorSetGroup&) = delete; + SHVkDescriptorSetGroup(SHVkDescriptorSetGroup&& rhs) noexcept = default; + /// + /// Destructor which will unload and deallocate all resources for this Descriptor Set. + /// + ~SHVkDescriptorSetGroup() noexcept; - /*-----------------------------------------------------------------------------*/ - /* Overloaded Operators */ - /*-----------------------------------------------------------------------------*/ - SHVkDescriptorSetGroup& operator=(const SHVkDescriptorSetGroup&) = delete; - SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + SHVkDescriptorSetGroup& operator=(const SHVkDescriptorSetGroup&) = delete; + SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; - /*-----------------------------------------------------------------------------*/ - /* Getter Functions */ - /*-----------------------------------------------------------------------------*/ - /// - /// Retrieves the handle to the Vulkan Descriptor Set handle. - /// - /// Handle to the Vulkan Descriptor Set. - [[nodiscard]] - inline const std::vector& GetVkHandle() { return descSets; } + /*-----------------------------------------------------------------------------*/ + /* Descriptor set writing */ + /*-----------------------------------------------------------------------------*/ + void ModifyWriteDescImage (uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept; + void UpdateDescriptorSet (void) noexcept; - private: - /*-----------------------------------------------------------------------------*/ - /* Data Members */ - /*-----------------------------------------------------------------------------*/ - Handle device; - Handle descPool; - std::vector descSets; - }; + /*-----------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves the handle to the Vulkan Descriptor Set handle. + /// + /// Handle to the Vulkan Descriptor Set. + [[nodiscard]] + inline const std::vector& GetVkHandle() { return descSets; } + private: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + //! Device required to allocate descriptor sets + Handle device; + + //! Descriptor pool to allocate descriptor sets + Handle descPool; + + //! Descriptor sets + std::vector descSets; + + //! for updating descriptor sets. We want to cache this so that we don't create the + //! write structs at runtime. + SHDescriptorSetUpdater updater; + + }; } diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp index 36eaa8e8..da1a3645 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp @@ -85,6 +85,11 @@ namespace SHADE device->GetVkLogicalDevice().destroyDescriptorSetLayout(setLayout); } + std::vector const& SHVkDescriptorSetLayout::GetBindings(void) const noexcept + { + return layoutDesc; + } + SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept { if (&rhs == this) diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h index 590fd787..1acba189 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h @@ -96,6 +96,7 @@ namespace SHADE /// /// Handle to the Vulkan Descriptor Set Layout handle. inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } + std::vector const& GetBindings (void) const noexcept; private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp index 69e76246..da4947f2 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -552,6 +552,22 @@ namespace SHADE return SHVkInstance::GetResourceManager().Create(GetHandle()); } + /***************************************************************************/ + /*! + + \brief + Writes to descriptor sets. + + \param writeDescSets + Descriptor sets to write to. + + */ + /***************************************************************************/ + void SHVkLogicalDevice::UpdateDescriptorSets(std::vector const& writeDescSets) noexcept + { + vkLogicalDevice.updateDescriptorSets(writeDescSets, {}); + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h index d50d27f0..c359d1d3 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h @@ -38,6 +38,7 @@ namespace SHADE class SHVkFramebuffer; class SHVkImageView; class SHShaderBlockInterface; + class SHVkDescriptorSetGroup; /***************************************************************************/ /*! @@ -179,6 +180,8 @@ namespace SHADE Handle CreateFence (void) const noexcept; Handle CreateSemaphore (void) const noexcept; + void UpdateDescriptorSets (std::vector const& writeDescSets) noexcept; + /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index d9761adf..4d4ca4f4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -84,8 +84,6 @@ namespace SHADE //commandBuffers[i] = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); // works } - - descPool = device->CreateDescriptorPools(); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 68af135f..8a7ce8a0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -209,9 +209,10 @@ namespace SHADE */ /***************************************************************************/ - SHRenderGraphNode::SHSubpass::SHSubpass(std::unordered_map const* mapping, std::unordered_map> const* resources) noexcept + SHRenderGraphNode::SHSubpass::SHSubpass(Handle const& parent, std::unordered_map const* mapping, std::unordered_map> const* resources) noexcept : resourceAttachmentMapping{ mapping } , ptrToResources{ resources } + , parentNode{ parent } { } @@ -333,6 +334,38 @@ namespace SHADE inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); } + void SHRenderGraphNode::SHSubpass::Execute(Handle& commandBuffer) noexcept + { + // Draw all the batches + + // Draw all the exterior draw calls + for (auto& drawCall : exteriorDrawCalls) + { + drawCall(commandBuffer); + } + } + + void SHRenderGraphNode::SHSubpass::AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept + { + exteriorDrawCalls.push_back(newDrawCall); + } + + /***************************************************************************/ + /*! + + \brief + Getter for parent renderpass. + + \return + Returns the parent renderpass the subpass belongs to. + + */ + /***************************************************************************/ + Handle const& SHRenderGraphNode::SHSubpass::GetParentNode(void) const noexcept + { + return parentNode; + } + /***************************************************************************/ /*! @@ -512,11 +545,26 @@ namespace SHADE } // Add subpass to container and create mapping for it - subpasses.emplace_back(resourceManager.Create(&resourceAttachmentMapping, ptrToResources)); - subpassIndexing.try_emplace(subpassName, subpasses.size() - 1); + subpasses.emplace_back(resourceManager.Create(GetHandle(), &resourceAttachmentMapping, ptrToResources)); + subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); return subpasses.at(subpassIndexing[subpassName]); } + void SHRenderGraphNode::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept + { + commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); + + for (auto& subpass : subpasses) + { + subpass->Execute(commandBuffer); + + // Go to next subpass + commandBuffer->NextSubpass(); + } + + commandBuffer->EndRenderpass(); + } + /***************************************************************************/ /*! @@ -560,7 +608,7 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint32_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) + void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) { // If we set to if (w == static_cast(-1) && h == static_cast(-1)) @@ -832,6 +880,20 @@ namespace SHADE } } + /***************************************************************************/ + /*! + + \brief + Configures command pools and command buffers. + + */ + /***************************************************************************/ + void SHRenderGraph::ConfigureCommands(void) noexcept + { + commandPool = logicalDeviceHdl->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); + commandBuffers.resize(static_cast(swapchainHdl->GetNumImages())); + } + /***************************************************************************/ /*! @@ -929,7 +991,7 @@ namespace SHADE } nodes.emplace_back(resourceManager.Create(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources)); - nodeIndexing.emplace(nodeName, nodes.size() - 1); + nodeIndexing.emplace(nodeName, static_cast(nodes.size()) - 1u); return nodes.at(nodeIndexing[nodeName]); } @@ -952,6 +1014,20 @@ namespace SHADE ConfigureSubpasses(); ConfigureRenderpasses(); ConfigureFramebuffers(); + ConfigureCommands(); + } + + void SHRenderGraph::Execute(uint32_t frameIndex) noexcept + { + auto& cmdBuffer = commandBuffers[frameIndex]; + cmdBuffer->BeginRecording(); + + for (auto& node : nodes) + { + node->Execute(commandBuffers[frameIndex], frameIndex); + } + + cmdBuffer->EndRenderpass(); } Handle SHRenderGraph::GetNode(std::string const& nodeName) const noexcept diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index dc6b7c42..ea913baa 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -15,6 +15,8 @@ namespace SHADE class SHVkImage; class SHVkImageView; class SHVkFramebuffer; + class SHVkCommandPool; + class SHVkCommandBuffer; // Used for attachment description creation for renderpass node enum class SH_ATT_DESC_TYPE @@ -72,25 +74,44 @@ namespace SHADE friend class SHRenderGraph; }; - class SHRenderGraphNode + class SHRenderGraphNode : public ISelfHandle { public: class SHSubpass { public: - SHSubpass(std::unordered_map const* mapping, std::unordered_map> const* ptrToResources) noexcept; + /*-----------------------------------------------------------------------*/ + /* CTORS AND DTORS */ + /*-----------------------------------------------------------------------*/ + SHSubpass(Handle const& parent, std::unordered_map const* mapping, std::unordered_map> const* ptrToResources) noexcept; SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept; + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + // Preparation functions void AddColorOutput (std::string resourceToReference) noexcept; void AddDepthOutput (std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept; void AddInput (std::string resourceToReference) noexcept; + + // Runtime functions + void Execute (Handle& commandBuffer) noexcept; + void AddExteriorDrawCalls (std::function&)> const& newDrawCall) noexcept; + + /*-----------------------------------------------------------------------*/ + /* GETTERS AND SETTERS */ + /*-----------------------------------------------------------------------*/ + Handle const& GetParentNode (void) const noexcept; private: /*---------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*---------------------------------------------------------------------*/ + //! The parent renderpass that this subpass belongs to + Handle parentNode; + //! Color attachments std::vector colorReferences; @@ -106,6 +127,14 @@ namespace SHADE //! Pointer to resources in the render graph (for getting handle IDs) std::unordered_map> const* ptrToResources; + //! Sometimes there exists entities that we want to render onto a render target + //! but don't want it to come from the batching system. An example would be ImGUI. + //! For these entities we want to link a function from the outside and draw them + //! after we draw everything from the batch. Because of this, these draw calls + //! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING + //! COMPLEX. + std::vector&)>> exteriorDrawCalls; + friend class SHRenderGraphNode; friend class SHRenderGraph; }; @@ -179,6 +208,7 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ Handle AddSubpass (std::string subpassName) noexcept; + void Execute (Handle& commandBuffer, uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ @@ -198,6 +228,7 @@ namespace SHADE void ConfigureSubpasses (void) noexcept; void ConfigureRenderpasses (void) noexcept; void ConfigureFramebuffers (void) noexcept; + void ConfigureCommands (void) noexcept; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -219,6 +250,13 @@ namespace SHADE //! Resource library for graph handles ResourceManager resourceManager; + //! Command pool for the render graph + Handle commandPool; + + //! Command buffers for the render graph + std::vector> commandBuffers; + + public: /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ @@ -228,10 +266,11 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle const& logicalDevice, Handle const& swapchain) noexcept; - void AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint32_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); - Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; - void Generate (void) noexcept; + void Init (Handle const& logicalDevice, Handle const& swapchain) noexcept; + void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); + Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; + void Generate (void) noexcept; + void Execute (uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp index 8beb7d98..1e5fb074 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp @@ -189,7 +189,7 @@ namespace SHADE Handle SHShaderDescriptorBindingInfo::GetShaderBlockInterface(uint32_t set, uint32_t binding) const noexcept { - SHShaderDescriptorBindingInfo::BindingAndSetHash hash = binding; + BindingAndSetHash hash = binding; hash |= static_cast(set) << 32; if (blockInterfaces.contains(hash)) return blockInterfaces.at(hash); diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h index 1250b54f..88c7a2e1 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h @@ -9,11 +9,10 @@ namespace SHADE { + using BindingAndSetHash = uint64_t; + struct SHShaderDescriptorBindingInfo { - public: - using BindingAndSetHash = uint64_t; - private: /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */