diff --git a/SHADE_Application/SHADE_Application.vcxproj b/SHADE_Application/SHADE_Application.vcxproj index ab1ac84c..c1775b8d 100644 --- a/SHADE_Application/SHADE_Application.vcxproj +++ b/SHADE_Application/SHADE_Application.vcxproj @@ -46,6 +46,7 @@ bin-int\Debug_x86_64\SHADE_Application\ SHADE_Application .exe + ..\Dependencies\spdlog\include;$(VULKAN_SDK)\include;..\Dependencies\VMA\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;$(IncludePath) false @@ -53,6 +54,7 @@ bin-int\Release_x86_64\SHADE_Application\ SHADE_Application .exe + ..\Dependencies\spdlog\include;$(VULKAN_SDK)\include;..\Dependencies\VMA\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;$(IncludePath) @@ -60,7 +62,7 @@ SBpch.h Level4 NOMINMAX;_DEBUG;%(PreprocessorDefinitions) - ..\Dependencies\spdlog\include;$(VULKAN_SDK)\include;..\Dependencies\VMA\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories) + ..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories) EditAndContinue Disabled false @@ -80,7 +82,7 @@ SBpch.h Level4 NOMINMAX;_RELEASE;%(PreprocessorDefinitions) - ..\Dependencies\spdlog\include;$(VULKAN_SDK)\include;..\Dependencies\VMA\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories) + ..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories) Full true true diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua index 74a3d0de..d6efc890 100644 --- a/SHADE_Application/premake5.lua +++ b/SHADE_Application/premake5.lua @@ -22,14 +22,20 @@ project "SHADE_Application" includedirs { - "%{IncludeDir.spdlog}/include", - "%{IncludeDir.VULKAN}/include", - "%{IncludeDir.VMA}/include", - "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect", "../SHADE_Engine/src", "src" } + + externalincludedirs + { + "%{IncludeDir.spdlog}/include", + "%{IncludeDir.VULKAN}/include", + "%{IncludeDir.VMA}/include", + "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect" + } + externalwarnings "Off" + flags { "MultiProcessorCompile" diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 69662415..a30237dc 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -2,9 +2,10 @@ #include "SBApplication.h" #include "Engine/ECS_Base/System/SHSystemManager.h" +#define SHEDITOR #ifdef SHEDITOR -#include "Editor/SHEditor.h" -#include "Scenes/SBEditorScene.h" +//#include "Editor/SHEditor.h" +//#include "Scenes/SBEditorScene.h" #endif // SHEDITOR #include @@ -29,8 +30,8 @@ namespace Sandbox graphicsSystem->SetWindow(&window); SHADE::SHSystemManager::Init(); - #ifdef SHEDITOR + //SHADE::SHEditor::Initialize(window.GetHWND()); #else #endif @@ -43,10 +44,15 @@ namespace Sandbox //TODO: Change true to window is open while (!window.WindowShouldClose()) { + //#ifdef SHEDITOR + //SHADE::SHEditor::PreRender(); + //#endif graphicsSystem->BeginRender(); - #ifdef SHEDITOR - #else - #endif + //#ifdef SHEDITOR + //SHADE::SHEditor::PreRender(); + //SHADE::SHEditor::Update(); + //SHADE::SHEditor::Render(); + //#endif graphicsSystem->EndRender(); } } @@ -54,6 +60,7 @@ namespace Sandbox void SBApplication::Exit(void) { + //SHADE::SHEditor::Exit(); SHADE::SHSystemManager::Exit(); #ifdef SHEDITOR diff --git a/SHADE_Engine/SHADE_Engine.vcxproj b/SHADE_Engine/SHADE_Engine.vcxproj index 3d1c506f..0925c31e 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj +++ b/SHADE_Engine/SHADE_Engine.vcxproj @@ -45,12 +45,14 @@ bin-int\Debug_x86_64\SHADE_Engine\ SHADE_Engine .lib + ..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\ktx\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;$(IncludePath) bin\Release_x86_64\SHADE_Engine\ bin-int\Release_x86_64\SHADE_Engine\ SHADE_Engine .lib + ..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\ktx\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;$(IncludePath) @@ -58,7 +60,7 @@ SHpch.h Level4 _LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;_DEBUG;%(PreprocessorDefinitions) - src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\ktx\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;%(AdditionalIncludeDirectories) + src;%(AdditionalIncludeDirectories) EditAndContinue Disabled false @@ -81,7 +83,7 @@ SHpch.h Level4 _LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;_RELEASE;%(PreprocessorDefinitions) - src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\ktx\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;%(AdditionalIncludeDirectories) + src;%(AdditionalIncludeDirectories) Full true true @@ -125,6 +127,7 @@ + @@ -135,6 +138,7 @@ + @@ -201,6 +205,7 @@ + @@ -210,6 +215,7 @@ + diff --git a/SHADE_Engine/SHADE_Engine.vcxproj.filters b/SHADE_Engine/SHADE_Engine.vcxproj.filters index ceb9b80f..1810f10f 100644 --- a/SHADE_Engine/SHADE_Engine.vcxproj.filters +++ b/SHADE_Engine/SHADE_Engine.vcxproj.filters @@ -177,6 +177,9 @@ Graphics\Descriptors + + Graphics\Descriptors + Graphics\Descriptors @@ -207,6 +210,9 @@ Graphics\Images + + Graphics\Images + Graphics\Instance @@ -399,6 +405,9 @@ Graphics\Descriptors + + Graphics\Descriptors + Graphics\Descriptors @@ -426,6 +435,9 @@ Graphics\Images + + Graphics\Images + Graphics\Instance diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index fbc800d3..c51b1ca6 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -21,7 +21,11 @@ project "SHADE_Engine" includedirs { "%{prj.location}/src", - "%{IncludeDir.assimp}/include", + } + + externalincludedirs + { + "%{IncludeDir.assimp}/include", "%{IncludeDir.imgui}", "%{IncludeDir.imguizmo}", "%{IncludeDir.imnodes}", @@ -38,6 +42,8 @@ project "SHADE_Engine" "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect" } + externalwarnings "Off" + libdirs { "%{prj.location}/libs", diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp index 4158d3c3..7913574c 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp @@ -33,6 +33,8 @@ namespace SHADE }; cmdBufferHdl->GetVkCommandBuffer().copyBuffer(stagingBuffer, vkBuffer, 1, ©Region); } + + // TODO: Need to destroy staging buffer. Obviously not here but after the command has finished executing. } vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h index 2ad3e4e9..9df1a1d0 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h @@ -48,7 +48,6 @@ namespace SHADE vk::BufferUsageFlags bufferUsageFlags; //! Reference to the allocator - //VmaAllocator const& vmaAllocator; std::reference_wrapper vmaAllocator; /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 6a307230..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); + } + /***************************************************************************/ /*! @@ -406,6 +411,31 @@ namespace SHADE } + + void SHVkCommandBuffer::PipelineBarrier ( + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept + { + vkCommandBuffer.pipelineBarrier ( + srcStage, + dstStage, + deps, + memoryBarriers, + bufferMemoryBarriers, + imageMemoryBarriers + ); + } + + //void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept + //{ + // //vkCommandBuffer.pipelineBarrier() + //} + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index 08fc45f7..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; @@ -114,6 +115,17 @@ namespace SHADE void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept; void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept; + // memory barriers + void PipelineBarrier ( + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + 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/Debugging/SHVulkanDebugUtil.cpp b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp index d63a65f7..0152e6c9 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp +++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp @@ -59,7 +59,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVulkanDebugUtil::ReportVkWarning(vk::Result vkResult, std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkWarning(vk::Result vkResult, std::string_view message) noexcept { //std::cout << location.file_name() << ": " << location.function_name() << "|" << location.line() << "|" << // location.column() << "|: Warning: " << SHDebugUtil::VkResultToString(vkResult) << " | " << message << std::endl; @@ -88,7 +88,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVulkanDebugUtil::ReportVkError(vk::Result vkResult, std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkError(vk::Result vkResult, std::string_view message) noexcept { std::string toLogger = "Vulkan Warning: " + std::string(SHVulkanDebugUtil::VkResultToString(vkResult)) + " | " + std::string(message); @@ -96,7 +96,7 @@ namespace SHADE } - void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message) noexcept { SHLOGV_INFO(message); } diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h index 7bf583bb..af4ca3ef 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h +++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h @@ -15,9 +15,9 @@ namespace SHADE public: static VKAPI_ATTR VkBool32 VKAPI_CALL GenericDebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageSeverityFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); - static void ReportVkWarning(vk::Result vkResult, std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; - static void ReportVkError(vk::Result vkResult, std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; - static void ReportVkSuccess(std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; + static void ReportVkWarning(vk::Result vkResult, std::string_view message) noexcept; + static void ReportVkError(vk::Result vkResult, std::string_view message) noexcept; + static void ReportVkSuccess(std::string_view message) 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 0fa1c864..da4947f2 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -418,7 +418,12 @@ namespace SHADE /***************************************************************************/ Handle SHVkLogicalDevice::CreateImage(uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) const noexcept { - return SHVkInstance::GetResourceManager().Create(std::cref(vmaAllocator), w, h, levels, format, usage, create); + return SHVkInstance::GetResourceManager().Create(&vmaAllocator, w, h, levels, format, usage, create); + } + + Handle SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::span inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept + { + return SHVkInstance::GetResourceManager().Create(&vmaAllocator, imageDetails, data, dataSize, inMipOffsets, memUsage, allocFlags); } /***************************************************************************/ @@ -547,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 78108b94..c359d1d3 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h @@ -19,6 +19,7 @@ #include "vk_mem_alloc.h" #include "Graphics/Descriptors/SHVkDescriptorPool.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" +#include "Graphics/Images/SHVkImage.h" namespace SHADE { @@ -29,7 +30,6 @@ namespace SHADE class SHVkSurface; class SHVkSwapchain; class SHVkBuffer; - class SHVkImage; class SHVkFence; class SHVkSemaphore; class SHVkShaderModule; @@ -38,6 +38,7 @@ namespace SHADE class SHVkFramebuffer; class SHVkImageView; class SHShaderBlockInterface; + class SHVkDescriptorSetGroup; /***************************************************************************/ /*! @@ -138,14 +139,23 @@ namespace SHADE ) const noexcept; Handle CreateImage ( - uint32_t w, - uint32_t h, - uint8_t levels, - vk::Format format, - vk::ImageUsageFlags usage, - vk::ImageCreateFlags create + uint32_t w, + uint32_t h, + uint8_t levels, + vk::Format format, + vk::ImageUsageFlags usage, + vk::ImageCreateFlags create ) const noexcept; - + + Handle CreateImage ( + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags + ) noexcept; + Handle CreateShaderModule ( std::vector const& binaryData, std::string entryPoint, @@ -170,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/Images/SHVkImage.cpp b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp index 11fbe5dd..f3d5a7b5 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp @@ -5,14 +5,88 @@ #include "Tools/SHLogger.h" #include "SHVkImageView.h" #include "Graphics/Instance/SHVkInstance.h" +#include "Graphics/Buffers/SHVkBuffer.h" namespace SHADE { + /***************************************************************************/ + /*! + + \brief + If an image is a GPU only resource, we need to prep a staging buffer + to use for transferring data to the GPU. #NoteToSelf: I don't really + like this because its duplicate code. Should try to find a way to utilize + the logical device for this. + + \param data + Data to transfer. + + \param srcSize + Size in bytes of the data. + + */ + /***************************************************************************/ + void SHVkImage::PrepStagingBuffer(void* data, uint32_t srcSize) noexcept + { + // For creation of buffer + vk::BufferCreateInfo bufferInfo{}; + + // size stored same as GPU buffer + bufferInfo.size = srcSize; + + // We just want to set the transfer bit + bufferInfo.usage = vk::BufferUsageFlagBits::eTransferSrc; + + // sharing mode exclusive + bufferInfo.sharingMode = vk::SharingMode::eExclusive; + + // Set to auto detect bits + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + + // We want to just write all at once. Using random access bit could make this slow + allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + + // parameters of a vmaAllocation retrieved via vmaGetAllocationInfo + VmaAllocationInfo allocInfo; + + // results of allocation + VmaAllocation stagingAlloc; + + // To get around VMA's usage for C version of vulkan, create a temp first..., + VkBuffer tempBuffer{}; + + // Create the buffer... + vmaCreateBuffer(*vmaAllocator, + &bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?) + &allocCreateInfo, + &tempBuffer, &stagingAlloc, &allocInfo); + + // then assign it to the hpp version + stagingBuffer = tempBuffer; + + // Just map, copy then unmap + void* stagingBufferMappedPtr = nullptr; + vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr); + + if (stagingBufferMappedPtr) + std::memcpy(static_cast(stagingBufferMappedPtr), static_cast(data), srcSize); + + const VkDeviceSize offsets = 0; + const VkDeviceSize sizes = srcSize; + vmaFlushAllocations(*vmaAllocator, 1, &stagingAlloc, &offsets, &sizes); + + vmaUnmapMemory(*vmaAllocator, stagingAlloc); + } + SHVkImage::SHVkImage( - VmaAllocator const& vmaAllocator, - SHImageCreateParams const& imageDetails, - VmaMemoryUsage memUsage, - VmaAllocationCreateFlags allocFlags + VmaAllocator const* allocator, + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags ) noexcept : imageType { imageDetails.imageType } , width{ imageDetails.width } @@ -23,12 +97,14 @@ namespace SHADE , imageFormat{ imageDetails.imageFormat } , usageFlags{} , createFlags{} + , vmaAllocator{allocator} + , mipOffsets { inMipOffsets } + , boundToCoherent{false} + , randomAccessOptimized {false} + , mappedPtr{nullptr} { - for (auto& bit : imageDetails.usageBits) - usageFlags |= bit; - - for (auto& bit : imageDetails.createBits) - createFlags |= bit; + usageFlags = imageDetails.usageFlags; + createFlags = imageDetails.createFlags; // If marked as 2D array compatible, image type MUST be 3D if (createFlags & vk::ImageCreateFlagBits::e2DArrayCompatible) @@ -64,58 +140,52 @@ namespace SHADE VmaAllocationInfo allocInfo{}; VkImage tempImage; - vmaCreateImage(vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo&(), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo&(), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + + if (result != VK_SUCCESS) + SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. "); + else + SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. "); + vkImage = tempImage; - //if (allocFlags & ) + // At this point the image and device memory have been created. + + if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) + randomAccessOptimized = true; + + // TODO: This constructor can only create a GPU only resource for now. Due to time constraint, I was trying to create a ctor + // fast to finish up the ImGUI backend. In the future, there definitely needs to be more versatility to the constructor. + + // Get the memory property flags + VkMemoryPropertyFlags memPropFlags; + vmaGetAllocationMemoryProperties(*vmaAllocator, alloc, &memPropFlags); + + // mainly host visible. Can be cached (need to flush/invalidate), uncached (always coherent) and coherent (virtual). + //if (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + //{ + // // If memory is marked to be coherent between CPU and GPU (no need flush/invalidate) (TODO: Verify if VMA_ALLOCATION_CREATE_MAPPED_BIT is used when VMA_MEMORY_USAGE_AUTO is set) + // // TODO: also verify that coherent bit = pointer is already mapped + // if (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + // { + // boundToCoherent = true; + // mappedPtr = allocInfo.pMappedData; + // } + // else + // mappedPtr = nullptr; + + // if (data) + // MapWriteUnmap(data, srcSize, 0, 0); + //} + //else + //{ + // We can prep first so that we can do transfers later via 1 cmd buffer recording + PrepStagingBuffer(data, dataSize); + + //} } - /***************************************************************************/ - /*! - - \brief - This is mainly used for images that aren't created internally because - they cannot be created in the traditional way (e.g. swapchain images). - - \param inVkImage - Image already created outside - - \param width - Width of the image - - \param height - Height of the image - - \param depth - Depth of the image - - \param levels - Number of levels in the image - - \param arrayLayers - if the image is an array, this value will be > 1. - - \param imageFormat - Format of the image - - */ - /***************************************************************************/ - SHVkImage::SHVkImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t arrayLayers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept - : vkImage (inVkImage) - , width{ inWidth } - , height{ inHeight } - , depth{ inDepth } - , mipLevelCount{ levels } - , layerCount{ arrayLayers } - , imageFormat{ format } - , usageFlags{flags} - , alloc{} - , imageType{type} - , createFlags{} - { - } - - SHVkImage::SHVkImage(VmaAllocator const& vmaAllocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept + SHVkImage::SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept : width {w} , height{h} , depth {1} @@ -124,6 +194,7 @@ namespace SHADE , imageFormat{format} , usageFlags{usage} , createFlags {create} + , vmaAllocator {allocator} { vk::ImageCreateInfo imageCreateInfo{}; imageCreateInfo.imageType = vk::ImageType::e2D; @@ -149,7 +220,7 @@ namespace SHADE VmaAllocationInfo allocInfo{}; VkImage tempImage; - auto result = vmaCreateImage(vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo); vkImage = tempImage; if (result != VK_SUCCESS) @@ -163,6 +234,86 @@ namespace SHADE return SHVkInstance::GetResourceManager().Create(inLogicalDeviceHdl, parent, createParams); } + void SHVkImage::TransferToDeviceResource(Handle const& cmdBufferHdl) noexcept + { + // prepare copy regions + std::vector copyRegions{mipOffsets.size()}; + + for (uint32_t i = 0; i < mipOffsets.size(); ++i) + { + copyRegions[i].bufferOffset = mipOffsets[i]; + copyRegions[i].bufferRowLength = 0; // for padding + copyRegions[i].bufferImageHeight = 0; // for padding + copyRegions[i].imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format. + copyRegions[i].imageSubresource.mipLevel = i; + copyRegions[i].imageSubresource.baseArrayLayer = 0; // TODO: Array textures not supported yet + copyRegions[i].imageSubresource.layerCount = layerCount; + copyRegions[i].imageOffset = vk::Offset3D{ 0,0,0 }; + copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 }; + } + + } + + /***************************************************************************/ + /*! + + \brief + Does not perform any image transitions but prepares a barrier for image + transitioning. Pipeline barrier will be issued outside this call after + this preparation function, or at least, it should be. + + \param oldLayout + Old layout of the image. + + \param newLayout + new layout of the image to transition to. + + \param barrier + Barrier to modify to prepare the image for transitioning. + + */ + /***************************************************************************/ + void SHVkImage::PrepareImageTransition(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept + { + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = vkImage; + barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format. + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = mipLevelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = layerCount; + + vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe; + + if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + dstStage = vk::PipelineStageFlagBits::eTransfer; + + barrier.srcAccessMask = vk::AccessFlagBits::eNone; + barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; + } + else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTransfer; + + // TODO, what if we want to access in compute shader + dstStage = vk::PipelineStageFlagBits::eFragmentShader; + + barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + } + else + { + SHLOG_ERROR("Image layouts are invalid. "); + } + + } + void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept { vkImage = inVkImage; diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.h b/SHADE_Engine/src/Graphics/Images/SHVkImage.h index 53066075..a30b90e6 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.h +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.h @@ -10,6 +10,7 @@ namespace SHADE { class SHVkLogicalDevice; class SHVkImageView; + class SHVkCommandBuffer; struct SHImageCreateParams { @@ -35,10 +36,10 @@ namespace SHADE vk::Format imageFormat; //! Image usage bits - std::span usageBits; + vk::ImageUsageFlags usageFlags; //! Image create flags - std::span createBits; + vk::ImageCreateFlags createFlags; }; class SHVkImage @@ -47,6 +48,12 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*-----------------------------------------------------------------------*/ + //! Pointer to the vma allocator. #NoteToSelf: Not super proud of this being a pointer. + //! The only reason why this is a pointer is because a reference_wrapper cannot be default constructed. + //! And the reason why we want a default constructor is because sometimes we don't want to create images + //! but merely link them from outside (swapchain images) + VmaAllocator const* vmaAllocator; + //! 1D, 2D or 3D vk::ImageType imageType = vk::ImageType::e2D; @@ -80,22 +87,46 @@ namespace SHADE //! allocation object containing details of an allocation VmaAllocation alloc{}; + //! Whether or not this image is HOST_VISIBLE and random access optimized + bool randomAccessOptimized; + + //! Whether or not the memory the image is bound to is memory coherent (updates on CPU can be seen on GPU without flushing cache) + bool boundToCoherent; + + //! Persistently mapped pointer if applicable (will be void if image is + //! not created with the correct flags). Note that this is only used for + //! persistent mapping. One time updates do not use this pointer. + void* mappedPtr; + + //! Staging buffer for images purely in the GPU + vk::Buffer stagingBuffer; + + //! Mipmap offsets for initializing the vk::BufferImageCopy during transfer to GPU resource + std::span mipOffsets; + + /*-----------------------------------------------------------------------*/ + /* PRIVATE MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void PrepStagingBuffer(void* data, uint32_t srcSize) noexcept; + + public: /*-----------------------------------------------------------------------*/ /* CTOR AND DTOR */ /*-----------------------------------------------------------------------*/ SHVkImage(void) noexcept = default; - // TODO: Might need to add flags to parameters SHVkImage( - VmaAllocator const& vmaAllocator, - SHImageCreateParams const& imageDetails, - VmaMemoryUsage memUsage, - VmaAllocationCreateFlags allocFlags + VmaAllocator const* allocator, + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags ) noexcept; - SHVkImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t arrayLayers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept; - SHVkImage(VmaAllocator const& vmaAllocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept; + SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept; SHVkImage(SHVkImage&& rhs) noexcept = default; SHVkImage& operator=(SHVkImage && rhs) noexcept = default; @@ -103,7 +134,9 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - Handle CreateImageView(Handle const& inLogicalDeviceHdl, Handle const& parent, SHImageViewDetails const& createParams) const noexcept; + Handle CreateImageView (Handle const& inLogicalDeviceHdl, Handle const& parent, SHImageViewDetails const& createParams) const noexcept; + void TransferToDeviceResource (Handle const& cmdBufferHdl) noexcept; + void PrepareImageTransition (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp new file mode 100644 index 00000000..e7a97126 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp @@ -0,0 +1,7 @@ +#include "SHpch.h" +#include "SHVkSampler.h" + +namespace SHADE +{ + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.h b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h new file mode 100644 index 00000000..d58edb8f --- /dev/null +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Graphics/SHVulkanIncludes.h" + +namespace SHADE +{ + struct SHVkSamplerParams + { + vk::Filter minFilter; + vk::Filter maxFilter; + //vk::Filter maxFilter; + }; + + class SHVkSampler + { + private: + //! The vulkan sampler handler + vk::Sampler vkSampler; + + public: + SHVkSampler () noexcept; + SHVkSampler (SHVkSampler&& rhs) noexcept; + SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; + + }; +} + 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/Pipeline/SHPipelineState.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp index 8179444f..6094958e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp @@ -117,7 +117,7 @@ namespace SHADE dirty = isDirty; } - std::tuple SHVertexInputState::GetInfoFromAttribFormat(SHAttribFormat attribFormat) const noexcept + std::tuple SHVertexInputState::GetInfoFromAttribFormat(SHAttribFormat attribFormat) const noexcept { switch (attribFormat) { @@ -138,6 +138,9 @@ namespace SHADE case SHAttribFormat::MAT_4D: return std::make_tuple(4, 16, vk::Format::eR32G32B32A32Sfloat); break; + + case SHAttribFormat::UINT32_1D: + return std::make_tuple(1, 4, vk::Format::eR32Uint); } return std::make_tuple(0, 0, vk::Format::eR32Sfloat); } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 4ad29f73..71bac1e6 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -182,12 +182,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Destructor for resource. - - */ + + */ /***************************************************************************/ SHRenderGraphResource::~SHRenderGraphResource(void) noexcept { @@ -195,37 +195,38 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Subpass non-default constructor. Simply initializes variables. - + \param mapping Mapping from a resource handle to an attachment reference referencing the resource. \param resources A mapping from string to render graph resource. - - */ + + */ /***************************************************************************/ - 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 } { } /***************************************************************************/ - /*! - + /*! + \brief Move constructor for subpass. - + \param rhs The subpass the move from. - - */ + + */ /***************************************************************************/ SHRenderGraphNode::SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept : colorReferences{ std::move(rhs.colorReferences) } @@ -238,15 +239,15 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Move assignment operator for subpass. - + \param rhs subpass to move from. - - */ + + */ /***************************************************************************/ SHRenderGraphNode::SHSubpass& SHRenderGraphNode::SHSubpass::operator=(SHSubpass&& rhs) noexcept { @@ -263,16 +264,16 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief - Adds a color output to a subpass. Takes in a string and finds the + Adds a color output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. - + \param resourceToReference Resource name to find resource to attach. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddColorOutput(std::string resourceToReference) noexcept { @@ -280,8 +281,8 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Adds a depth output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. @@ -292,8 +293,8 @@ namespace SHADE \param attachmentDescriptionType Depending on the type of the resource, initialize the image layout appropriately. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept { @@ -317,8 +318,8 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Adds a input output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. @@ -326,21 +327,53 @@ namespace SHADE \param resourceToReference Resource name to find resource to attach. - */ + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddInput(std::string resourceToReference) noexcept { 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 - Creates a renderpass for the node. Uses subpass and attachment + Getter for parent renderpass. + + \return + Returns the parent renderpass the subpass belongs to. + + */ + /***************************************************************************/ + Handle const& SHRenderGraphNode::SHSubpass::GetParentNode(void) const noexcept + { + return parentNode; + } + + /***************************************************************************/ + /*! + + \brief + Creates a renderpass for the node. Uses subpass and attachment descriptions already configured beforehand in the render graph. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::CreateRenderpass(void) noexcept { @@ -348,12 +381,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Creates a framebuffer from the images used in the renderpass. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::CreateFramebuffer(void) noexcept { @@ -489,18 +522,18 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Add subpasses to the renderpass and returns a reference to it. - + \param subpassName Name of the subpass. - + \return Handle to the new subpass. - - */ + + */ /***************************************************************************/ Handle SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept { @@ -512,20 +545,35 @@ 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(); + } + /***************************************************************************/ /*! - + \brief Get the renderpass from the node. - - \return + + \return Handle to the renderpass. - + */ /***************************************************************************/ Handle SHRenderGraphNode::GetRenderpass(void) const noexcept @@ -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)) @@ -663,16 +711,16 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Configures the supasses; mainly the subpass descriptions and the subpass dependencies involved between subpasses. - - - \return - - */ + + + \return + + */ /***************************************************************************/ void SHRenderGraph::ConfigureSubpasses(void) noexcept { @@ -801,12 +849,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Simply loops through all nodes and create renderpasses. - - */ + + */ /***************************************************************************/ void SHRenderGraph::ConfigureRenderpasses(void) noexcept { @@ -817,12 +865,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Simply loops through all nodes and create framebuffers. - - */ + + */ /***************************************************************************/ void SHRenderGraph::ConfigureFramebuffers(void) noexcept { @@ -836,7 +884,21 @@ namespace SHADE /*! \brief - Init function. Doesn't do much except initialize device and swapchain + 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())); + } + + /***************************************************************************/ + /*! + + \brief + Init function. Doesn't do much except initialize device and swapchain handle. Graph should start out empty. \param swapchain @@ -854,15 +916,15 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Default ctor, doesn't do much. - - - \return - - */ + + + \return + + */ /***************************************************************************/ SHRenderGraph::SHRenderGraph(void) noexcept : logicalDeviceHdl{ } @@ -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,14 +1014,20 @@ namespace SHADE ConfigureSubpasses(); ConfigureRenderpasses(); ConfigureFramebuffers(); + ConfigureCommands(); } - void SHRenderGraph::Execute(void) noexcept + 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 7ba49e84..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 */ @@ -229,10 +267,10 @@ 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 = {}); + 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 (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 */ diff --git a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h index fd8ee3d1..b216f5f4 100644 --- a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h +++ b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h @@ -18,7 +18,10 @@ namespace SHADE // that a mat2 can be interpreted as (x, y, x, y), (o, o, o, o) instead of (x, y, o, o), (o, o, o, o)? MAT_2D, MAT_3D, - MAT_4D + MAT_4D, + + // integer formats + UINT32_1D, }; struct SHVertexAttribute diff --git a/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp b/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp index 6ac6672b..957ffc34 100644 --- a/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp +++ b/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp @@ -222,7 +222,7 @@ namespace SHADE return true; { MSG Message; - while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE)) + while (PeekMessageW(&Message, wndHWND, 0, 0, PM_REMOVE)) { if (WM_QUIT == Message.message) {