From d4fe63722a480eb18cbd24840a17eb007b695a0d Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Sun, 23 Oct 2022 15:05:31 +0800 Subject: [PATCH] WIP (TODO: remember to change commit message) --- Assets/Editor/Layouts/UserLayout.ini | 26 +-- .../Graphics/Commands/SHVkCommandBuffer.cpp | 30 ++- .../src/Graphics/Commands/SHVkCommandBuffer.h | 25 ++- .../Descriptors/SHVkDescriptorSetGroup.cpp | 9 +- .../Descriptors/SHVkDescriptorSetGroup.h | 2 + .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 4 +- .../MiddleEnd/Batching/SHSuperBatch.cpp | 140 ++++++------- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 33 ++- .../Interface/SHPostOffscreenRenderSystem.cpp | 2 +- .../MiddleEnd/Interface/SHRenderer.cpp | 2 +- .../src/Graphics/Pipeline/SHPipelineType.h | 6 +- .../src/Graphics/Pipeline/SHVkPipeline.cpp | 26 +-- .../src/Graphics/Pipeline/SHVkPipeline.h | 1 + .../Graphics/Pipeline/SHVkPipelineLayout.cpp | 32 +-- .../Graphics/Pipeline/SHVkPipelineLayout.h | 12 +- .../RenderGraph/SHAttachmentDescriptionType.h | 3 +- .../Graphics/RenderGraph/SHRenderGraph.cpp | 71 +++---- .../src/Graphics/RenderGraph/SHRenderGraph.h | 12 +- .../RenderGraph/SHRenderGraphNode.cpp | 82 +++++++- .../Graphics/RenderGraph/SHRenderGraphNode.h | 9 + .../RenderGraph/SHRenderGraphNodeCompute.cpp | 109 ++++++++++ .../RenderGraph/SHRenderGraphNodeCompute.h | 57 +++++ .../RenderGraph/SHRenderGraphResource.cpp | 8 + .../RenderGraph/SHRenderGraphResource.h | 2 + .../RenderGraph/SHRenderGraphStorage.h | 15 +- .../src/Graphics/RenderGraph/SHSubpass.cpp | 194 +++++++++--------- .../src/Graphics/RenderGraph/SHSubpass.h | 7 +- .../Graphics/RenderGraph/SHSubpassCompute.cpp | 53 ----- .../Graphics/RenderGraph/SHSubpassCompute.h | 49 ----- SHADE_Engine/src/Graphics/SHVkUtil.cpp | 15 ++ SHADE_Engine/src/Graphics/SHVkUtil.h | 12 +- TempShaderFolder/GreyscaleCs.glsl | 38 ---- TempShaderFolder/GreyscaleCs.spv | Bin 1400 -> 0 bytes TempShaderFolder/KirschCs.glsl | 167 +++++++++++++++ TempShaderFolder/KirschCs.spv | Bin 0 -> 5900 bytes 35 files changed, 788 insertions(+), 465 deletions(-) create mode 100644 SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp create mode 100644 SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h delete mode 100644 SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp delete mode 100644 SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h delete mode 100644 TempShaderFolder/GreyscaleCs.glsl delete mode 100644 TempShaderFolder/GreyscaleCs.spv create mode 100644 TempShaderFolder/KirschCs.glsl create mode 100644 TempShaderFolder/KirschCs.spv diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 530ee770..005c3556 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -1,16 +1,16 @@ [Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 +Pos=0,1367 +Size=3440,20 Collapsed=0 [Window][SHEditorMenuBar] Pos=0,48 -Size=1920,1012 +Size=3440,1319 Collapsed=0 [Window][Hierarchy Panel] -Pos=0,142 -Size=571,918 +Pos=0,170 +Size=646,1197 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,29 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1649,48 -Size=271,1012 +Pos=3169,48 +Size=271,1319 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] Pos=0,48 -Size=571,92 +Size=646,120 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=573,48 -Size=1074,1012 +Pos=648,48 +Size=2519,1319 Collapsed=0 DockId=0x00000002,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=3440,1319 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=571,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=646,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1074,1036 CentralNode=1 Selected=0x13926F0B + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=999,1036 CentralNode=1 Selected=0x13926F0B DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 4501ba7b..a744c795 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -10,6 +10,7 @@ #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Images/SHVkImage.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" +#include "Graphics/SHVkUtil.h" namespace SHADE @@ -299,7 +300,7 @@ namespace SHADE SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); return; } - boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout(); + bindPointData[static_cast(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout(); vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline()); } @@ -358,9 +359,10 @@ namespace SHADE } } - void SHVkCommandBuffer::BindDescriptorSet(Handle descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span dynamicOffsets) + void SHVkCommandBuffer::BindDescriptorSet(Handle descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span dynamicOffsets) { - vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); + uint32_t bindPointIndex = static_cast(bindPoint); + vkCommandBuffer.bindDescriptorSets(SHVkUtil::GetPipelineBindPointFromType(bindPoint), bindPointData[bindPointIndex].boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); } /***************************************************************************/ @@ -452,6 +454,11 @@ namespace SHADE vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); } + void SHVkCommandBuffer::ComputeDispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept + { + vkCommandBuffer.dispatch (groupCountX, groupCountY, groupCountZ); + } + void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo) { vkCommandBuffer.copyBufferToImage @@ -500,9 +507,9 @@ namespace SHADE // //vkCommandBuffer.pipelineBarrier() //} - void SHVkCommandBuffer::ForceSetPipelineLayout(Handle pipelineLayout) noexcept + void SHVkCommandBuffer::ForceSetPipelineLayout(Handle pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept { - boundPipelineLayoutHdl = pipelineLayout; + bindPointData[static_cast(pipelineType)].boundPipelineLayoutHdl = pipelineLayout; } /***************************************************************************/ @@ -513,12 +520,13 @@ namespace SHADE */ /***************************************************************************/ - void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept + void SHVkCommandBuffer::SubmitPushConstants(SH_PIPELINE_TYPE bindPoint) const noexcept { - vkCommandBuffer.pushConstants(boundPipelineLayoutHdl->GetVkPipelineLayout(), - boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(), + auto layoutHdl = bindPointData[static_cast(bindPoint)].boundPipelineLayoutHdl; + vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(), + layoutHdl->GetPushConstantInterface().GetShaderStageFlags(), 0, - boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData); + layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData); } /***************************************************************************/ @@ -695,7 +703,7 @@ namespace SHADE , usageFlags{ rhs.usageFlags } , commandBufferCount{ rhs.commandBufferCount } , parentPool{ rhs.parentPool } - , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } + , bindPointData{ std::move (rhs.bindPointData)} { memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); @@ -728,7 +736,7 @@ namespace SHADE usageFlags = rhs.usageFlags; commandBufferCount = rhs.commandBufferCount; parentPool = rhs.parentPool; - boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl; + bindPointData = std::move(rhs.bindPointData); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); rhs.vkCommandBuffer = VK_NULL_HANDLE; diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index 9416a1aa..70a209ee 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h @@ -6,6 +6,7 @@ #include "SHCommandPoolResetMode.h" #include "Resource/ResourceLibrary.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h" +#include "Graphics/Pipeline/SHPipelineType.h" namespace SHADE { @@ -39,7 +40,14 @@ namespace SHADE friend class ResourceLibrary; static constexpr uint16_t PUSH_CONSTANT_SIZE = 512; + private: + struct PipelineBindPointData + { + //! The currently bound pipeline + Handle boundPipelineLayoutHdl; + }; + /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*-----------------------------------------------------------------------*/ @@ -66,8 +74,8 @@ namespace SHADE //! The command pool that this command buffer belongs to Handle parentPool; - //! The currently bound pipeline - Handle boundPipelineLayoutHdl; + //! Every command buffer will have a set of pipeline bind point specific data + std::array(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData; //! The push constant data for the command buffer uint8_t pushConstantData[PUSH_CONSTANT_SIZE]; @@ -112,13 +120,16 @@ namespace SHADE void BindPipeline (Handle const& pipelineHdl) noexcept; void BindVertexBuffer (uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept; void BindIndexBuffer (Handle const& buffer, uint32_t startingIndex) const noexcept; - void BindDescriptorSet (Handle descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span dynamicOffsets); + void BindDescriptorSet (Handle descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span dynamicOffsets); // Draw Commands 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; void DrawMultiIndirect (Handle indirectDrawData, uint32_t drawCount); + // Compute Commands + void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept; + // Buffer Copy void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo); void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector& copyInfo); @@ -138,13 +149,13 @@ namespace SHADE // Push Constant variable setting template - void SetPushConstantVariable(std::string variableName, T const& data) noexcept + void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept { - memcpy (static_cast(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); + memcpy (static_cast(pushConstantData) + bindPointData[static_cast(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); }; - void ForceSetPipelineLayout (Handle pipelineLayout) noexcept; + void ForceSetPipelineLayout (Handle pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept; - void SubmitPushConstants (void) const noexcept; + void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp index ea859718..de68c583 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp @@ -91,7 +91,7 @@ namespace SHADE // new write for the binding updater.writeInfos.emplace_back(); - updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); + updater.writeHashMap.try_emplace(writeHash, static_cast(updater.writeInfos.size()) - 1u); auto& writeInfo = updater.writeInfos.back(); // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in @@ -102,10 +102,10 @@ namespace SHADE //case vk::DescriptorType::eSampler: //case vk::DescriptorType::eSampledImage: case vk::DescriptorType::eCombinedImageSampler: + case vk::DescriptorType::eStorageImage: + case vk::DescriptorType::eInputAttachment: writeInfo.descImageInfos.resize(descriptorCount); - break; - //case vk::DescriptorType::eStorageImage: - // break; + break; case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eUniformBuffer: @@ -165,6 +165,7 @@ namespace SHADE if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) { SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); + return; } for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h index f2b886e8..85c3ef97 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h @@ -31,6 +31,8 @@ namespace SHADE class SHVkDescriptorSetGroup { public: + using viewSamplerLayout = std::tuple, Handle, vk::ImageLayout>; + /*-----------------------------------------------------------------------------*/ /* Constructor/Destructors */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 2705b4d1..40826047 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -369,7 +369,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ void SHBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) { - if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index."); return; @@ -385,7 +385,7 @@ namespace SHADE cmdBuffer->BindDescriptorSet ( matPropsDescSet[frameIndex], - vk::PipelineBindPoint::eGraphics, + SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, dynamicOffset ); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index add51196..14f2aa76 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -20,91 +20,91 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Constructor/Destructors */ - /*---------------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + /* Constructor/Destructors */ + /*---------------------------------------------------------------------------------*/ - SHSuperBatch::SHSuperBatch(Handle sp) - : subpass { sp } - {} + SHSuperBatch::SHSuperBatch(Handle sp) + : subpass{ sp } + {} - /*---------------------------------------------------------------------------------*/ - /* Usage Functions */ - /*---------------------------------------------------------------------------------*/ - void SHSuperBatch::Add(const SHRenderable* renderable) noexcept + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + void SHSuperBatch::Add(const SHRenderable* renderable) noexcept + { + const Handle PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); + + // Check if we have a batch with the same pipeline first + auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch) + { + return batch.GetPipeline() == PIPELINE; + }); + + + // Create one if not found + if (batch == batches.end()) { - const Handle PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); - - // Check if we have a batch with the same pipeline first - auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch) - { - return batch.GetPipeline() == PIPELINE; - }); - - - // Create one if not found - if (batch == batches.end()) - { - batches.emplace_back(PIPELINE); - batch = batches.end() - 1; - } - - // Add renderable in - batch->Add(renderable); + batches.emplace_back(PIPELINE); + batch = batches.end() - 1; } - void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept + // Add renderable in + batch->Add(renderable); + } + + void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept + { + const Handle PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); + + // Check if we have a Batch with the same pipeline yet + auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch) + { + return batch.GetPipeline() == PIPELINE; + }); + + // Attempt to remove if it exists + if (batch == batches.end()) + return; + + batch->Remove(renderable); + } + + void SHSuperBatch::Clear() noexcept + { + for (auto& batch : batches) { - const Handle PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); - - // Check if we have a Batch with the same pipeline yet - auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch) - { - return batch.GetPipeline() == PIPELINE; - }); - - // Attempt to remove if it exists - if (batch == batches.end()) - return; - - batch->Remove(renderable); + batch.Clear(); } + batches.clear(); + } - void SHSuperBatch::Clear() noexcept + void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle descPool) + { + for (auto& batch : batches) { - for (auto& batch : batches) - { - batch.Clear(); - } - batches.clear(); + batch.UpdateMaterialBuffer(frameIndex, descPool); + batch.UpdateTransformBuffer(frameIndex); + batch.UpdateEIDBuffer(frameIndex); } + } - void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle descPool) + void SHSuperBatch::Build(Handle device, Handle descPool, uint32_t frameIndex) noexcept + { + // Build all batches + for (auto& batch : batches) { - for (auto& batch : batches) - { - batch.UpdateMaterialBuffer(frameIndex, descPool); - batch.UpdateTransformBuffer(frameIndex); - batch.UpdateEIDBuffer(frameIndex); - } + batch.Build(device, descPool, frameIndex); } + } - void SHSuperBatch::Build(Handle device, Handle descPool, uint32_t frameIndex) noexcept + void SHSuperBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept + { + // Build all batches + for (auto& batch : batches) { - // Build all batches - for (auto& batch : batches) - { - batch.Build(device, descPool, frameIndex); - } - } - - void SHSuperBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept - { - // Build all batches - for (auto& batch : batches) - { - batch.Draw(cmdBuffer, frameIndex); - } + batch.Draw(cmdBuffer, frameIndex); } + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 386cef54..992cbdf1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -123,12 +123,12 @@ namespace SHADE shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true); shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true); - shaderSourceLibrary.LoadShader(2, "GreyscaleCs.glsl", SH_SHADER_TYPE::COMPUTE, true); + shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true); shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary); auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); - auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl"); + auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); cubeVS->Reflect(); cubeFS->Reflect(); greyscale->Reflect(); @@ -171,28 +171,25 @@ namespace SHADE // Initialize world render graph worldRenderGraph->Init(device, swapchain); - worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second); + worldRenderGraph->AddResource("Scene Pre Postprocess", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); + worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); - auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors + auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre Postprocess"}, {}); // no predecessors //First subpass to write to G-Buffer auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); - gBufferWriteSubpass->AddColorOutput("Scene"); + gBufferWriteSubpass->AddColorOutput("Scene Pre Postprocess"); gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); - auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl"); - - auto greyscaleSubpass = node->AddSubpass("Greyscale Subpass"); - greyscaleSubpass->AddGeneralInput("Scene"); - greyscaleSubpass->AddSubpassCompute(greyscale); - - // We do this to just transition our scene layout to shader read - auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); - sceneLayoutTransitionSubpass->AddInput("Scene"); + //auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); + //sceneLayoutTransitionSubpass->AddGeneralInput("Scene"); + + auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); + node->AddNodeCompute (greyscale, {"Scene Pre Postprocess", "Scene"}); // Generate world render graph worldRenderGraph->Generate(); @@ -375,7 +372,7 @@ namespace SHADE uint32_t h = static_cast(viewports[vpIndex]->GetHeight()); currentCmdBuffer->SetViewportScissor (static_cast(w), static_cast(h), w, h); - currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout()); + currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS); // Bind all the buffers required for meshes for (auto& [buffer, bindingPoint] : MESH_DATA) @@ -395,7 +392,7 @@ namespace SHADE currentCmdBuffer->BindDescriptorSet ( textureDescSet, - vk::PipelineBindPoint::eGraphics, + SH_PIPELINE_TYPE::GRAPHICS, 0, texDynamicOffset ); @@ -741,8 +738,8 @@ namespace SHADE auto cameraSystem = SHSystemManager::GetSystem(); #ifdef SHEDITOR - cameraSystem->GetEditorCamera()->SetWidth(resizeWidth); - cameraSystem->GetEditorCamera()->SetHeight(resizeHeight); + cameraSystem->GetEditorCamera()->SetWidth(static_cast(resizeWidth)); + cameraSystem->GetEditorCamera()->SetHeight(static_cast(resizeHeight)); #else #endif diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp index 8b41a979..ebce5c9e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp @@ -68,7 +68,7 @@ namespace SHADE { std::vector combinedImageSampler { - std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal), + std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral), }; // Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp index 2532f308..a1806ccd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderer.cpp @@ -82,7 +82,7 @@ namespace SHADE std::array dynamicOffsets{ frameIndex * cameraDataAlignedSize }; - cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); + cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); } } diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h index e7f5b6a8..2c1c80ff 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineType.h @@ -5,9 +5,13 @@ namespace SHADE { enum class SH_PIPELINE_TYPE { - GRAPHICS, + GRAPHICS = 0, COMPUTE, + RAY_TRACING, + NUM_TYPES, }; + + } #endif \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp index 973218d1..973ae72f 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp @@ -4,6 +4,7 @@ #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h" #include "Graphics/RenderGraph/SHRenderGraph.h" +#include "Graphics/SHVkUtil.h" namespace SHADE { @@ -268,7 +269,7 @@ namespace SHADE , logicalDeviceHdl{ rhs.logicalDeviceHdl } , pipelineLayout { rhs.pipelineLayout } { - vkPipeline = VK_NULL_HANDLE; + rhs.vkPipeline = VK_NULL_HANDLE; } /***************************************************************************/ @@ -308,7 +309,8 @@ namespace SHADE /***************************************************************************/ SHVkPipeline::~SHVkPipeline(void) noexcept { - logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr); + if (vkPipeline) + logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr); } /***************************************************************************/ @@ -336,7 +338,7 @@ namespace SHADE created = rhs.created; logicalDeviceHdl = rhs.logicalDeviceHdl; - vkPipeline = VK_NULL_HANDLE; + rhs.vkPipeline = VK_NULL_HANDLE; return *this; } @@ -422,18 +424,7 @@ namespace SHADE /***************************************************************************/ vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept { - switch (pipelineType) - { - case SH_PIPELINE_TYPE::GRAPHICS: - return vk::PipelineBindPoint::eGraphics; - case SH_PIPELINE_TYPE::COMPUTE: - return vk::PipelineBindPoint::eCompute; - break; - default: - return vk::PipelineBindPoint::eGraphics; - break; - - } + return SHVkUtil::GetPipelineBindPointFromType(pipelineType); } /***************************************************************************/ @@ -473,4 +464,9 @@ namespace SHADE return pipelineLayout; } + SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept + { + return pipelineType; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h index fe55a41e..9ec18650 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.h @@ -77,6 +77,7 @@ namespace SHADE vk::Pipeline GetVkPipeline (void) const noexcept; bool GetIsCreated (void) const noexcept; Handle GetPipelineLayout (void) const noexcept; + SH_PIPELINE_TYPE GetPipelineType (void) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp index 7a76447d..37d00795 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp @@ -216,9 +216,18 @@ namespace SHADE /***************************************************************************/ void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept { + // pipeline layouts contain global layouts first, then layouts for allocation descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size()); + vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size()); - // Settle allocate layouts first + // First we insert the global layouts + for (auto const& layout : descriptorSetLayoutsGlobal) + { + descriptorSetLayoutsPipeline.emplace_back(layout); + //vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle()); + } + + // Then the allocate layouts vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size()); for (auto const& layout : descriptorSetLayoutsAllocate) { @@ -226,18 +235,13 @@ namespace SHADE vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle()); } - // pipeline layouts contain global layouts first, then layouts for allocation - vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size()); - - // First we insert the global layouts - for (auto const& layout : descriptorSetLayoutsGlobal) + for (auto const& layout : descriptorSetLayoutsPipeline) { - descriptorSetLayoutsPipeline.emplace_back(layout); vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle()); } // Then we append layouts for allocation at the back of the vector - std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline)); + //std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline)); } /***************************************************************************/ @@ -294,6 +298,7 @@ namespace SHADE , descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this , descriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{} + , descriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{} { for (auto& mod : shaderModules) @@ -318,6 +323,7 @@ namespace SHADE , descriptorSetLayoutsGlobal{} , descriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{} + , descriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{} { @@ -368,7 +374,8 @@ namespace SHADE , descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)} , descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)} , vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)} - , vkDescriptorSetLayoutsPipeline{std::move (rhs.vkDescriptorSetLayoutsAllocate)} + , descriptorSetLayoutsPipeline { std::move(rhs.descriptorSetLayoutsPipeline) } + , vkDescriptorSetLayoutsPipeline{ std::move(rhs.vkDescriptorSetLayoutsPipeline) } { rhs.vkPipelineLayout = VK_NULL_HANDLE; } @@ -441,12 +448,12 @@ namespace SHADE return {}; } - std::vector> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept + std::vector> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept { return descriptorSetLayoutsPipeline; } - std::vector> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept + std::vector> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept { return descriptorSetLayoutsAllocate; } @@ -464,7 +471,8 @@ namespace SHADE descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal); descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate); vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate); - vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsAllocate); + descriptorSetLayoutsPipeline = std::move(rhs.descriptorSetLayoutsPipeline); + vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsPipeline); rhs.vkPipelineLayout = VK_NULL_HANDLE; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h index f5d363fa..b4298e00 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h @@ -74,12 +74,12 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ - std::vector> const& GetShaderModules (void) const noexcept; - vk::PipelineLayout GetVkPipelineLayout (void) const noexcept; - SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept; - Handle GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept; - std::vector> GetDescriptorSetLayoutsPipeline(void) const noexcept; - std::vector> GetDescriptorSetLayoutsAllocate(void) const noexcept; + std::vector> const& GetShaderModules (void) const noexcept; + vk::PipelineLayout GetVkPipelineLayout (void) const noexcept; + SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept; + Handle GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept; + std::vector> const& GetDescriptorSetLayoutsPipeline(void) const noexcept; + std::vector> const& GetDescriptorSetLayoutsAllocate(void) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h index efd3fb0f..c4d44ea8 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHAttachmentDescriptionType.h @@ -10,7 +10,8 @@ namespace SHADE DEPTH = 0x04, STENCIL = 0x08, DEPTH_STENCIL = 0x10, - INPUT = 0x20 + INPUT = 0x20, + STORAGE = 0x40 }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index df588c05..1c0798f1 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -10,7 +10,7 @@ #include "Tools/SHLogger.h" #include "SHAttachmentDescInitParams.h" #include "SHRenderGraphStorage.h" -#include "Graphics/RenderGraph/SHSubpassCompute.h" +#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" namespace SHADE { @@ -59,7 +59,7 @@ namespace SHADE format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format; } - graphResources.try_emplace(resourceName, resourceManager->Create(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); + renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); } /***************************************************************************/ @@ -104,16 +104,6 @@ namespace SHADE for (auto& input : subpass->inputReferences) resourceAttFinalLayouts[input.attachment] = input.layout; - - // Go through all subpass computes and initialize final layouts to GENERAL when a resource is detected to be used in it - //for (auto sbCompute : subpass->subpassComputes) - //{ - // auto const& indices = sbCompute->attachmentDescriptionIndices; - // for (auto& index : indices) - // { - // resourceAttFinalLayouts[index] = vk::ImageLayout::eGeneral; - // } - //} } for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j) @@ -188,7 +178,7 @@ namespace SHADE // Now we want to loop through all attachments in all subpasses in the node and query // the resources being used. For each resource we want to query the type and record it // in bit fields (1 bit for each subpass). - uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0, descriptorDependencies = 0; + uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0; uint32_t i = 0; @@ -227,9 +217,6 @@ namespace SHADE if (subpass->inputReferences.size()) inputDependencies |= (1 << i); - if (!subpass->subpassComputes.empty()) - descriptorDependencies |= (1 << i); - // Input attachments can be any type, so we need to check what type it is for (auto& inputAtt : subpass->inputReferences) { @@ -295,12 +282,6 @@ namespace SHADE dstAccess |= vk::AccessFlagBits::eInputAttachmentRead; } - if (descriptorDependencies & (1 << i)) - { - dstStage |= vk::PipelineStageFlagBits::eComputeShader; - dstAccess |= vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eShaderRead; - } - //// If subpass of first renderpass, stage flag should be bottom of pipe //if (&node == &nodes.front() && i == 0) // srcStage = vk::PipelineStageFlagBits::eBottomOfPipe; @@ -316,8 +297,8 @@ namespace SHADE dep.srcStageMask = srcStage; - // initialize the barriers - //node->subpasses[i]->InitComputeBarriers(); + // initialize input descriptors + node->subpasses[i]->CreateInputDescriptors(); } } } @@ -371,15 +352,16 @@ namespace SHADE /***************************************************************************/ void SHRenderGraph::Init(Handle logicalDevice, Handle swapchain) noexcept { + resourceManager = std::make_shared(); + renderGraphStorage = resourceManager->Create(); + renderGraphStorage->graphResources = resourceManager->Create>>(); renderGraphStorage->logicalDevice = logicalDevice; renderGraphStorage->swapchain = swapchain; renderGraphStorage->resourceManager = resourceManager; renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); - - renderGraphStorage->ptrToResources = &graphResources; } /***************************************************************************/ @@ -396,20 +378,17 @@ namespace SHADE SHRenderGraph::SHRenderGraph(void) noexcept : renderGraphStorage{} , nodes{} - , graphResources{} , resourceManager{nullptr} { - resourceManager = std::make_shared(); } SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept : renderGraphStorage{ rhs.renderGraphStorage } , nodeIndexing{ std::move(rhs.nodeIndexing) } , nodes{ std::move(rhs.nodes) } - , graphResources{ std::move(rhs.graphResources) } , resourceManager{ std::move(rhs.resourceManager) } { - + } SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept @@ -420,7 +399,6 @@ namespace SHADE renderGraphStorage = rhs.renderGraphStorage; nodeIndexing = std::move(rhs.nodeIndexing); nodes = std::move(rhs.nodes); - graphResources = std::move(rhs.graphResources); resourceManager = std::move(rhs.resourceManager); return *this; @@ -456,12 +434,12 @@ namespace SHADE for (auto const& instruction : resourceInstruction) { // If the resource that the new node is requesting for exists, allow the graph to reference it - if (graphResources.contains(instruction.resourceName)) + if (renderGraphStorage->graphResources->contains(instruction.resourceName)) { descInitParams.push_back( { - .resourceHdl = graphResources.at(instruction.resourceName), - .dontClearOnLoad = false, + .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName), + .dontClearOnLoad = instruction.dontClearOnLoad, } ); } @@ -506,12 +484,31 @@ namespace SHADE /***************************************************************************/ void SHRenderGraph::Generate(void) noexcept { + CheckForNodeComputes(); ConfigureAttachmentDescriptions(); ConfigureSubpasses(); ConfigureRenderpasses(); ConfigureFramebuffers(); } + /***************************************************************************/ + /*! + + \brief + This function goes through all renderpasses and checks for existence of + node computes. If they exist, adds dummy subpasses to transition resources + into general. + + */ + /***************************************************************************/ + void SHRenderGraph::CheckForNodeComputes(void) noexcept + { + for (auto& node : nodes) + { + node->AddDummySubpassIfNeeded(); + } + } + // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // better way to manage these void SHRenderGraph::Execute(uint32_t frameIndex, Handle cmdBuffer, Handle descPool) noexcept @@ -531,7 +528,7 @@ namespace SHADE void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept { // resize resources - for (auto& [name, resource]: graphResources) + for (auto& [name, resource] : *renderGraphStorage->graphResources) resource->HandleResize(newWidth, newHeight); for (auto& node : nodes) @@ -551,9 +548,9 @@ namespace SHADE Handle SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept { - if (graphResources.contains(resourceName)) + if (renderGraphStorage->graphResources->contains(resourceName)) { - return graphResources.at(resourceName); + return renderGraphStorage->graphResources->at(resourceName); } return {}; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index 529476cf..b445134c 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -66,9 +66,6 @@ namespace SHADE //! Render graph nodes std::vector> nodes; - //! Resources that exist for the entire render graph - std::unordered_map> graphResources; - //! Resource library for graph handles std::shared_ptr resourceManager; @@ -88,10 +85,11 @@ namespace SHADE void AddResource(std::string resourceName, std::initializer_list typeFlags, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); Handle AddNode (std::string nodeName, std::initializer_list resourceInstruction, std::initializer_list predecessorNodes) noexcept; - void Generate (void) noexcept; - void Execute (uint32_t frameIndex, Handle cmdBuffer, Handle descPool) noexcept; - void FinaliseBatch(uint32_t frameIndex, Handle descPool); - void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; + void Generate (void) noexcept; + void CheckForNodeComputes (void) noexcept; + void Execute (uint32_t frameIndex, Handle cmdBuffer, Handle descPool) noexcept; + void FinaliseBatch (uint32_t frameIndex, Handle descPool); + void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index 0d88a93a..c315bffd 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -7,6 +7,8 @@ #include "SHRenderGraphResource.h" #include "SHSubpass.h" #include "SHRenderGraphStorage.h" +#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" +#include "Graphics/SHVkUtil.h" namespace SHADE { @@ -80,7 +82,6 @@ namespace SHADE fbHeight = attResources[j]->height; } - framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight); } @@ -88,6 +89,11 @@ namespace SHADE { subpass->HandleResize(); } + + for (auto& nodeCompute : nodeComputes) + { + nodeCompute->HandleResize(); + } } /***************************************************************************/ @@ -121,6 +127,7 @@ namespace SHADE , subpasses{} , executed{ false } , configured{ false } + , nodeComputes{} { // pipeline library initialization pipelineLibrary.Init(graphStorage->logicalDevice); @@ -181,6 +188,7 @@ namespace SHADE , batcher{ std::move(rhs.batcher) } , spDescs{ std::move(rhs.spDescs) } , spDeps{ std::move(rhs.spDeps) } + , nodeComputes{ std::move(rhs.nodeComputes) } { rhs.renderpass = {}; @@ -204,6 +212,7 @@ namespace SHADE batcher = std::move(rhs.batcher); spDescs = std::move(rhs.spDescs); spDeps = std::move(rhs.spDeps); + nodeComputes = std::move(rhs.nodeComputes); rhs.renderpass = {}; @@ -235,7 +244,7 @@ namespace SHADE } // Add subpass to container and create mapping for it - subpasses.emplace_back(graphStorage->resourceManager->Create(graphStorage, GetHandle(), subpasses.size(), &resourceAttachmentMapping)); + subpasses.emplace_back(graphStorage->resourceManager->Create(graphStorage, GetHandle(), static_cast(subpasses.size()), &resourceAttachmentMapping)); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); subpass->Init(*graphStorage->resourceManager); @@ -246,21 +255,84 @@ namespace SHADE return subpass; } + Handle SHRenderGraphNode::AddNodeCompute(Handle computeShaderModule, std::initializer_list resources, float numWorkGroupScale/* = 1.0f*/) noexcept + { + // Look for the required resources in the graph + std::vector> nodeComputeResources{}; + nodeComputeResources.reserve(resources.size()); + + for (auto& resourceName : resources) + { + auto resource = graphStorage->graphResources->at(resourceName); + nodeComputeResources.push_back(resource); + } + + // Create the subpass compute with the resources + auto nodeCompute = graphStorage->resourceManager->Create(graphStorage, computeShaderModule, std::move(nodeComputeResources)); + nodeComputes.push_back(nodeCompute); + + return nodeCompute; + } + + /***************************************************************************/ + /*! + + \brief + This function checks all node computes and adds a subpass to transition + all needed resources to general. + + */ + /***************************************************************************/ + void SHRenderGraphNode::AddDummySubpassIfNeeded(void) noexcept + { + if (!nodeComputes.empty()) + { + // we save the resource names involved + std::unordered_set resourcesInvolved; + for (auto& compute : nodeComputes) + { + for (auto& resource : compute->resources) + { + resourcesInvolved.emplace(resource->GetName()); + } + } + + // insert them all for a subpass to transition them. This subpass is the last subpass + auto dummySubpass = AddSubpass("dummy"); + for (auto& resource : resourcesInvolved) + { + dummySubpass->AddGeneralInput(resource); + + if (SHVkUtil::IsDepthStencilAttachment(graphStorage->graphResources->at(resource)->GetResourceFormat())) + dummySubpass->AddGeneralDepthOutput(resource); + else + dummySubpass->AddGeneralColorOutput(resource); + } + } + } + void SHRenderGraphNode::Execute(Handle& commandBuffer, Handle descPool, uint32_t frameIndex) noexcept { - frameIndex = (framebuffers.size() > 1) ? frameIndex : 0; - commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); + uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0; + commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]); for (uint32_t i = 0; i < subpasses.size(); ++i) { subpasses[i]->Execute(commandBuffer, descPool, frameIndex); // Go to next subpass if not last subpass - if (i != subpasses.size() - 1) + if (i != static_cast(subpasses.size()) - 1u) commandBuffer->NextSubpass(); } commandBuffer->EndRenderpass(); + + + // Execute all subpass computes + for (auto& sbCompute : nodeComputes) + { + sbCompute->Execute(commandBuffer, frameIndex); + } } Handle SHRenderGraphNode::GetOrCreatePipeline(std::pair, Handle> const& vsFsPair, Handle subpass) noexcept diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index 7c3622ad..335b93e3 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -21,6 +21,7 @@ namespace SHADE class SHVkDescriptorPool; class SHGraphicsGlobalData; class SHRenderGraphStorage; + class SHRenderGraphNodeCompute; class SH_API SHRenderGraphNode : public ISelfHandle { @@ -67,6 +68,10 @@ namespace SHADE //! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass SHPipelineLibrary pipelineLibrary; + //! Sometimes we want the subpass to do something to the images instead + //! of drawing objects on the image (i.e. compute). + std::vector> nodeComputes; + //! Whether or not the node has finished execution bool executed; @@ -75,6 +80,7 @@ namespace SHADE SHBatcher batcher; + /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ @@ -94,6 +100,9 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ Handle AddSubpass(std::string subpassName) noexcept; + Handle AddNodeCompute(Handle computeShaderModule, std::initializer_list resources, float numWorkGroupScale = 1.0f) noexcept; + void AddDummySubpassIfNeeded (void) noexcept; + // TODO: RemoveSubpass() void Execute(Handle& commandBuffer, Handle descPool, uint32_t frameIndex) noexcept; Handle GetOrCreatePipeline(std::pair, Handle> const& vsFsPair, Handle subpass) noexcept; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp new file mode 100644 index 00000000..a5208fcf --- /dev/null +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.cpp @@ -0,0 +1,109 @@ +#include "SHpch.h" +#include "SHRenderGraphNodeCompute.h" +#include "Graphics/Pipeline/SHVkPipeline.h" +#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" +#include "Graphics/Descriptors/SHVkDescriptorPool.h" +#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Graphics/Pipeline/SHVkPipelineLayout.h" +#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" +#include "SHRenderGraphStorage.h" +#include "SHRenderGraphResource.h" +#include "Graphics/Commands/SHVkCommandBuffer.h" + +namespace SHADE +{ + SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept + : computePipeline{} + , pipelineLayout{} + , resources{} + , groupSizeX{0} + , groupSizeY{0} + , numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)} + { + SHPipelineLayoutParams pipelineLayoutParams + { + .shaderModules = {computeShaderModule}, + .globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts() + }; + + // Create pipeline layout from parameters + pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams); + + // Create the compute pipeline + computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout); + + // and construct it + computePipeline->ConstructPipeline(); + + // save the resources + resources = std::move (subpassComputeResources); + + //Get the descriptor set layouts required to allocate. We only want the ones for allocate because + //global descriptors are already bound in the main system. + auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate(); + + //Variable counts for the descriptor sets (all should be 1). + std::vector variableCounts{ static_cast(layouts.size()) }; + std::fill(variableCounts.begin(), variableCounts.end(), 0); + + // Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE) + for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts); + } + + + HandleResize(); + } + + void SHRenderGraphNodeCompute::Execute(Handle cmdBuffer, uint32_t frameIndex) noexcept + { + // bind the compute pipeline + cmdBuffer->BindPipeline(computePipeline); + + // bind descriptor sets + cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {}); + + // dispatch compute + cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1); + + // TODO: barrier + + } + + void SHRenderGraphNodeCompute::HandleResize(void) noexcept + { + // Get the layout for the render graph resource. We can index it this way because the container returned is a container of layouts that includes the global ones + auto pipelineDescSetLayouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE]; + + // everything below here needs resizing + for (uint32_t frameIndex = 0; frameIndex < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++frameIndex) + { + uint32_t i = 0; + + // loop through bindings and write descriptor sets + for (auto& binding : pipelineDescSetLayouts->GetBindings()) + { + uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0; + + SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle{}, vk::ImageLayout::eGeneral); + descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 }); + descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint); + ++i; + } + } + + // Get the group size from the max width and height + uint32_t maxWidth = 0, maxHeight = 0; + for (auto& resource : resources) + { + maxWidth = std::max(resource->GetWidth(), maxWidth); + maxHeight = std::max(resource->GetHeight(), maxHeight); + } + + groupSizeX = maxWidth / workGroupSizeX; + groupSizeY = maxHeight / workGroupSizeY; + } + +} diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h new file mode 100644 index 00000000..e35326f7 --- /dev/null +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNodeCompute.h @@ -0,0 +1,57 @@ +#pragma once + +#include "Resource/Handle.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" +#include +#include +#include + +namespace SHADE +{ + class SHVkPipeline; + class SHVkDescriptorSetGroup; + class SHVkDescriptorPool; + class SHVkLogicalDevice; + class SHVkPipelineLayout; + class SHRenderGraphStorage; + class SHRenderGraphResource; + class SHVkShaderModule; + class SHVkCommandBuffer; + + class SHRenderGraphNodeCompute + { + private: + static constexpr uint32_t workGroupSizeX = 16; + static constexpr uint32_t workGroupSizeY = 16; + + //! To run the dispatch command + Handle computePipeline; + + //! Pipeline layout for the pipeline creation + Handle pipelineLayout; + + //! Descriptor set group to hold the images for reading (STORAGE_IMAGE) + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups; + + //! vector of resources needed by the subpass compute + std::vector> resources; + + //! X dimension work group size. Should scale with resource size. + uint32_t groupSizeX; + + //! Y dimension work group size + uint32_t groupSizeY; + + float numWorkGroupScale; + + public: + SHRenderGraphNodeCompute(Handle graphStorage, Handle computeShaderModule, std::vector>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept; + + void Execute (Handle cmdBuffer, uint32_t frameIndex) noexcept; + void HandleResize (void) noexcept; + + friend class SHRenderGraph; + friend class SHRenderGraphNode; + }; +} + diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp index 651ba88b..502e09b2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.cpp @@ -117,6 +117,9 @@ namespace SHADE usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eSampled; break; + case SH_ATT_DESC_TYPE_FLAGS::STORAGE: + usage |= vk::ImageUsageFlagBits::eStorage; + break; case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT: { SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. "); @@ -334,4 +337,9 @@ namespace SHADE return mipLevels; } + std::string SHRenderGraphResource::GetName(void) const noexcept + { + return resourceName; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h index 55f25864..832fa772 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphResource.h @@ -88,9 +88,11 @@ namespace SHADE Handle GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; uint8_t GetMipLevels (void) const noexcept; + std::string GetName (void) const noexcept; friend class SHRenderGraphNode; friend class SHRenderGraph; friend class SHSubpass; + friend class SHRenderGraphNodeCompute; }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h index cb274697..f8123191 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphStorage.h @@ -9,13 +9,14 @@ namespace SHADE class SHVkSwapchain; class SHGraphicsGlobalData; class SHVkDescriptorPool; + class SHRenderGraphResource; class SHRenderGraphStorage { //! Logical device for creation of vulkan objects Handle logicalDevice; - //! swapchain hdl + //! swapchain handle Handle swapchain; //! Resource manager for creation of objects @@ -24,13 +25,19 @@ namespace SHADE //! Descriptor pool for the descriptor sets to be created in the subpasses Handle descriptorPool; - //! For accessing resources anyone in the graph - std::unordered_map> const* ptrToResources; + //! For accessing resources anywhere in the graph + Handle>> graphResources; + + //SHRenderGraphStorage(void) noexcept; + //SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept; + //SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept; friend class SHRenderGraph; friend class SHRenderGraphNode; friend class SHSubpass; friend class SHRenderGraphResource; - friend class SHSubpassCompute; + friend class SHRenderGraphNodeCompute; }; + + } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index e6472c52..5e3449c2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -7,7 +7,6 @@ #include "Graphics/Shaders/SHVkShaderModule.h" #include "SHRenderGraphNode.h" #include "SHRenderGraphStorage.h" -#include "Graphics/RenderGraph/SHSubpassCompute.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Images/SHVkSampler.h" @@ -40,7 +39,6 @@ namespace SHADE , depthReferences{} , inputReferences{} , graphStorage{ renderGraphStorage } - , subpassComputes{} , inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS} { } @@ -66,8 +64,12 @@ namespace SHADE , resourceAttachmentMapping{ rhs.resourceAttachmentMapping } , descriptorSetLayout{ rhs.descriptorSetLayout } , exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) } - , graphStorage{ std::move(rhs.graphStorage) } - , subpassComputes{std::move (rhs.subpassComputes)} + , graphStorage{ rhs.graphStorage } + , inputNames{ std::move(rhs.inputNames) } + , inputImageDescriptors{ std::move(rhs.inputImageDescriptors) } + , inputDescriptorLayout{ rhs.inputDescriptorLayout } + , inputSamplers{ rhs.inputSamplers } + { } @@ -97,8 +99,11 @@ namespace SHADE resourceAttachmentMapping = rhs.resourceAttachmentMapping; descriptorSetLayout = rhs.descriptorSetLayout; exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); - graphStorage = std::move(rhs.graphStorage); - subpassComputes = std::move(rhs.subpassComputes); + graphStorage = rhs.graphStorage; + inputNames = std::move(rhs.inputNames); + inputImageDescriptors = std::move(rhs.inputImageDescriptors); + inputDescriptorLayout = rhs.inputDescriptorLayout; + inputSamplers = rhs.inputSamplers; return *this; } @@ -117,7 +122,12 @@ namespace SHADE /***************************************************************************/ void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept { - colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal }); + colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal }); + } + + void SHSubpass::AddGeneralColorOutput(std::string resourceToReference) noexcept + { + colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral }); } /***************************************************************************/ @@ -154,7 +164,13 @@ namespace SHADE //Invalid return; } - depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), imageLayout }); + depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), imageLayout }); + } + + void SHSubpass::AddGeneralDepthOutput(std::string resourceToReference) noexcept + { + depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral }); + } /***************************************************************************/ @@ -171,15 +187,14 @@ namespace SHADE /***************************************************************************/ void SHSubpass::AddInput(std::string resourceToReference) noexcept { - inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); + inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); inputNames.push_back(resourceToReference); } void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept { - inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral }); - + inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral }); } void SHSubpass::Execute(Handle& commandBuffer, Handle descPool, uint32_t frameIndex) noexcept @@ -196,11 +211,6 @@ namespace SHADE drawCall(commandBuffer); } - // if there are subpass computes, transition all to GENERAL layout first - for (auto& sbCompute : subpassComputes) - { - - } } void SHSubpass::HandleResize(void) noexcept @@ -213,29 +223,6 @@ namespace SHADE exteriorDrawCalls.push_back(newDrawCall); } - Handle SHSubpass::AddSubpassCompute(Handle computeShaderModule/*, std::initializer_list resources*/) noexcept - { - //// for the subpass compute to store indices to the resources, see member comments - //std::unordered_set attDescIndices{}; - //attDescIndices.reserve (resources.size()); - - //// Look for the required resources in the graph - //std::vector> subpassComputeResources{}; - //subpassComputeResources.reserve(resources.size()); - - //for (auto& resourceName : resources) - //{ - // auto resource = graphStorage->ptrToResources->at(resourceName); - // subpassComputeResources.push_back(resource); - // attDescIndices.emplace(resourceAttachmentMapping->at (resource.GetId().Raw)); - //} - - // Create the subpass compute with the resources - auto subpassCompute = graphStorage->resourceManager->Create(graphStorage, computeShaderModule/*, std::move(subpassComputeResources), std::move (attDescIndices)*/); - subpassComputes.push_back(subpassCompute); - - return subpassCompute; - } void SHSubpass::Init(ResourceManager& resourceManager) noexcept { @@ -245,48 +232,51 @@ namespace SHADE void SHSubpass::CreateInputDescriptors(void) noexcept { - //std::vector bindings{}; + if (inputNames.empty()) + return; - //for (auto& input : inputReferences) - //{ - // SHVkDescriptorSetLayout::Binding newBinding - // { - // .Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage, - // .Stage = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute, - // .BindPoint = static_cast(bindings.size()), - // .DescriptorCount = 1, - // .flags = {}, - // }; + std::vector bindings{}; - // bindings.push_back(newBinding); - //} + for (auto& input : inputReferences) + { + SHVkDescriptorSetLayout::Binding newBinding + { + .Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage, + .Stage = vk::ShaderStageFlagBits::eFragment, + .BindPoint = static_cast(bindings.size()), + .DescriptorCount = 1, + .flags = {}, + }; - //// We build a new descriptor set layout to store our images - //inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings); + bindings.push_back(newBinding); + } - //// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle. - //for (uint32_t i = 0; i < bindings.size(); ++i) - //{ - // if (bindings[i].Type == vk::DescriptorType::eInputAttachment) - // { - // auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams - // { - // .minFilter = vk::Filter::eLinear, - // .magFilter = vk::Filter::eLinear, - // .addressMode = vk::SamplerAddressMode::eRepeat, - // .mipmapMode = vk::SamplerMipmapMode::eLinear, - // .minLod = -1000, - // .maxLod = 1000 - // } - // ); + // We build a new descriptor set layout to store our images + inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings); - // inputSamplers.push_back(newSampler); - // } - // else - // { - // inputSamplers.push_back({}); - // } - //} + // we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle. + for (uint32_t i = 0; i < bindings.size(); ++i) + { + if (bindings[i].Type == vk::DescriptorType::eInputAttachment) + { + auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams + { + .minFilter = vk::Filter::eLinear, + .magFilter = vk::Filter::eLinear, + .addressMode = vk::SamplerAddressMode::eRepeat, + .mipmapMode = vk::SamplerMipmapMode::eLinear, + .minLod = -1000, + .maxLod = 1000 + } + ); + + inputSamplers.push_back(newSampler); + } + else + { + inputSamplers.push_back({}); + } + } //// maybe do this in handle resize? //UpdateWriteDescriptors(); @@ -294,39 +284,43 @@ namespace SHADE void SHSubpass::UpdateWriteDescriptors(void) noexcept { - //auto const& bindings = inputDescriptorLayout->GetBindings(); + if (inputNames.empty()) + return; - //std::vector variableCounts{ static_cast(bindings.size()), 0 }; + auto const& bindings = inputDescriptorLayout->GetBindings(); - //uint32_t i = 0; + std::vector variableCounts{ static_cast(bindings.size()) }; + std::fill (variableCounts.begin(), variableCounts.end(), 0u); - //// For every frame's descriptor set - //for (auto& group : inputImageDescriptors) - //{ - // if (group) - // group.Free(); - // group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts); + // For every frame's descriptor set + for (auto& group : inputImageDescriptors) + { + if (group) + group.Free(); - // for (auto& binding : bindings) - // { - // // get the resource - // auto resource = graphStorage->ptrToResources->at(inputNames[binding.BindPoint]); + group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts); - // // If resource is swapchain image, get the correct image, if not just get 0. - // uint32_t viewIndex = (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; + uint32_t i = 0; + for (auto& binding : bindings) + { + // get the resource + auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]); - // // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL - // vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal; + // If resource is swapchain image, get the correct image, if not just get 0. + uint32_t viewIndex = (resource->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0; - // // Update descriptor sets - // auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout); - // group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1}); - // group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint); - // } + // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL + vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal; - // ++i; - //} + // Update descriptor sets + auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout); + group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1}); + group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint); + } + + ++i; + } } //void SHSubpass::InitComputeBarriers(void) noexcept diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index 48874a06..5a9dafb2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -17,7 +17,6 @@ namespace SHADE class SHVkDescriptorSetGroup; class SHVkDescriptorPool; class SHRenderGraphStorage; - class SHSubpassCompute; class SHVkShaderModule; class SHVkSampler; @@ -64,9 +63,6 @@ namespace SHADE std::vector> inputSamplers; - //! Sometimes we want the subpass to do something to the images instead - //! of drawing objects on the image (i.e. compute). - std::vector> subpassComputes; ////! subpass compute image barriers. We do this because every frame has a different ////! swapchain image. If the resource we want to transition is not a swapchain image, @@ -96,7 +92,9 @@ namespace SHADE /*-----------------------------------------------------------------------*/ // Preparation functions void AddColorOutput(std::string resourceToReference) noexcept; + void AddGeneralColorOutput(std::string resourceToReference) noexcept; void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept; + void AddGeneralDepthOutput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept; void AddGeneralInput (std::string resourceToReference) noexcept; void AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept; @@ -105,7 +103,6 @@ namespace SHADE void Execute(Handle& commandBuffer, Handle descPool, uint32_t frameIndex) noexcept; void HandleResize (void) noexcept; - Handle AddSubpassCompute(Handle computeShaderModule/*, std::initializer_list resources*/) noexcept; void Init(ResourceManager& resourceManager) noexcept; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp deleted file mode 100644 index 79242c7d..00000000 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "SHpch.h" -#include "SHSubpassCompute.h" -#include "Graphics/Pipeline/SHVkPipeline.h" -#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" -#include "Graphics/Descriptors/SHVkDescriptorPool.h" -#include "Graphics/Devices/SHVkLogicalDevice.h" -#include "Graphics/Pipeline/SHVkPipelineLayout.h" -#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" -#include "SHRenderGraphStorage.h" -//#include "" - -namespace SHADE -{ - SHSubpassCompute::SHSubpassCompute(Handle graphStorage, Handle computeShaderModule/*, std::vector>&& subpassComputeResources, std::unordered_set&& attDescIndices*/) noexcept - : pipeline{} - { - SHPipelineLayoutParams pipelineLayoutParams - { - .shaderModules = {computeShaderModule}, - .globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts() - }; - - // Create descriptor set from - pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams); - - // Create the compute pipeline - pipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout); - - pipeline->ConstructPipeline(); - - // Get the descriptor set layouts required to allocate. We only want the ones for allocate because - // global descriptors are already bound in the main system. - //auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate(); - - // Variable counts for the descriptor sets (all should be 1). - //std::vector variableCounts{ static_cast(layouts.size()) }; - //std::fill(variableCounts.begin(), variableCounts.end(), 0); - - //// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE) - //descSetGroup = graphStorage->descriptorPool->Allocate(layouts, variableCounts); - - //// save the resources - //resources = std::move (subpassComputeResources); - - //// we save this because when we configure the graph, we want to make sure final layouts - //// of attachment descriptions are set to GENERAL. See ConfigureAttachmentDescriptions in SHRenderGraph.cpp. - //attachmentDescriptionIndices = std::move (attDescIndices); - - //descSetGroup->ModifyWriteDescImage (SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, ) - } - - //SHSubpass -} diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h deleted file mode 100644 index aae2a9b9..00000000 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpassCompute.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "Resource/Handle.h" -#include -#include -#include - -namespace SHADE -{ - class SHVkPipeline; - class SHVkDescriptorSetGroup; - class SHVkDescriptorPool; - class SHVkLogicalDevice; - class SHVkPipelineLayout; - class SHRenderGraphStorage; - class SHRenderGraphResource; - class SHVkShaderModule; - - class SHSubpassCompute - { - private: - //! To run the dispatch command - Handle pipeline; - - //! Pipeline layout for the pipeline creation - Handle pipelineLayout; - - ////! Descriptor set group to hold the images for reading (STORAGE_IMAGE) - //Handle descSetGroup; - - ////! Required resources to be used in the descriptors - //std::vector resourcesRequired; - - ////! vector of resources needed by the subpass compute - //std::vector> resources; - - ////! we save this because when we configure the graph, we want to make sure final layouts - ////! of attachment descriptions are set to GENERAL. See ConfigureAttachmentDescriptions in SHRenderGraph.cpp. - //std::unordered_set attachmentDescriptionIndices{}; - - public: - SHSubpassCompute(Handle graphStorage, Handle computeShaderModule/*, std::vector>&& subpassComputeResources, std::unordered_set&& attDescIndices*/) noexcept; - - //void ExecuteSubpass (void) noexcept; - friend class SHRenderGraph; - friend class SHSubpass; - }; -} - diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index c8c563a1..cf486a7a 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -55,6 +55,21 @@ namespace SHADE return 0; } + vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept + { + switch (pipelineType) + { + case SH_PIPELINE_TYPE::GRAPHICS: + return vk::PipelineBindPoint::eGraphics; + case SH_PIPELINE_TYPE::COMPUTE: + return vk::PipelineBindPoint::eCompute; + case SH_PIPELINE_TYPE::RAY_TRACING: + return vk::PipelineBindPoint::eRayTracingKHR; + default: + return vk::PipelineBindPoint::eGraphics; + } + } + void SHVkUtil::EnsureBufferAndCopyData(Handle device, Handle cmdBuffer, Handle& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) { if (bufferHandle) diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.h b/SHADE_Engine/src/Graphics/SHVkUtil.h index ca3b6f83..ab11b537 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.h +++ b/SHADE_Engine/src/Graphics/SHVkUtil.h @@ -4,6 +4,7 @@ #include "SHVulkanIncludes.h" #include "Resource/Handle.h" +#include "Graphics/Pipeline/SHPipelineType.h" namespace SHADE { @@ -20,11 +21,12 @@ namespace SHADE class SHVkUtil { public: - static bool IsDepthOnlyFormat (vk::Format format) noexcept; - static bool IsDepthStencilAttachment (vk::Format format) noexcept; - static bool IsBlendCompatible (vk::Format format) noexcept; - static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept; - + static bool IsDepthOnlyFormat (vk::Format format) noexcept; + static bool IsDepthStencilAttachment (vk::Format format) noexcept; + static bool IsBlendCompatible (vk::Format format) noexcept; + static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept; + static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept; + /***********************************************************************************/ /*! diff --git a/TempShaderFolder/GreyscaleCs.glsl b/TempShaderFolder/GreyscaleCs.glsl deleted file mode 100644 index 3167a57c..00000000 --- a/TempShaderFolder/GreyscaleCs.glsl +++ /dev/null @@ -1,38 +0,0 @@ -/* Start Header *****************************************************************/ - -/*! \file (e.g. kirsch.comp) - - \author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920. - - \par william.zheng\@digipen.edu. brandon.hao\@digipen.edu. - - \date Sept 20, 2022 - - \brief Copyright (C) 20xx DigiPen Institute of Technology. - - Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */ - - /* End Header *******************************************************************/ - -#version 450 - -layout(local_size_x = 16, local_size_y = 16) in; -layout(set = 4, binding = 0, rgba8) uniform image2D targetImage; - - -void main() -{ - // load the image - vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID)); - - // get the average - float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; - - // store result into result image - imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f)); - -} - - - - diff --git a/TempShaderFolder/GreyscaleCs.spv b/TempShaderFolder/GreyscaleCs.spv deleted file mode 100644 index 5b36e00317061a12d75127def8a67c940e8969c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1400 zcmZ9K+fEZv6o$97g$e>9Ld9b%o)E04oRoku(M*~&0pb-`lVLh(CK*~%#wI3S=!H+< zjql+b_yoRy@8OM!|2NDsqkFQl*8i{5UTaTjWO2;7b8g&Cx@~uMX55Gv=O)}}roHyt zcJnmtG}qQwiI{SwERdLK#Z;urlH(xm;h2$J6c2Z1gX!XwSyFZ9z6+Gq)oc6S-k#Tf zfbRiXw{r!ROT@>?i$!bVc6<=`~7t}_mcimkhFTkei)>2zt?)5<&@oZ>0lTQi1$>J8n-3%GTe~O0W<4_ zggo$z94|=EYHH?gWE*gqJuiDyTwPLAydEOM)UOLyrQwhTO*Ae|yjJ(mp|0i7pF`}n zSTOhI%n46P*8w{8oR)^;Md@kp1W!Jgx#&s$taLrc;VzioHzgeNv*W|s=1cQ03e(^G4`hG+`DMraOTzRs|E6r`KK{*rF2o!w>dsue z3mii24gC$aL&0p8Ut;*L*#Yms|HK?%X5x*(JHqUGQo^3W^tdEpZy$u&(Ok|Qs4Dxa z<(!l=?n=%v>%QXHCI1ew_>RQU^Qwe?_;z($?gsZte(rWl0>@stkNsotpA`dcNO*_3 z#PaUQCXbz1-d)-7mUmA!?*soSuXSHG_3&A(hq9@)B(Yk{vf-`PifrBz-fBIPO+9?f z#-8D*!JeCv;+`K17x%m>3}-uiA{&ll+*8?b#XUb0CKjLFcTG0^4X^))H*&nMSK(c@ WB;*i>kN+^#y}2{>@&8uWEy*9dZd@?{ diff --git a/TempShaderFolder/KirschCs.glsl b/TempShaderFolder/KirschCs.glsl new file mode 100644 index 00000000..3dec174d --- /dev/null +++ b/TempShaderFolder/KirschCs.glsl @@ -0,0 +1,167 @@ +//#version 450 +// +//layout(local_size_x = 16, local_size_y = 16) in; +//layout(set = 4, binding = 0, rgba8) uniform image2D targetImage; +// +// +//void main() +//{ +// ivec2 imageSize = imageSize (targetImage); +// +// if (gl_GlobalInvocationID.x >= imageSize.x && gl_GlobalInvocationID.y >= imageSize.y) +// return; +// +// // load the image +// vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID)); +// +// // get the average +// float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; +// +// // store result into result image +// imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f)); +// +//} +// +// +// +// + +/* Start Header *****************************************************************/ + +/*! \file (e.g. kirsch.comp) + + \author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920. + + \par william.zheng\@digipen.edu. brandon.hao\@digipen.edu. + + \date Sept 20, 2022 + + \brief Copyright (C) 20xx DigiPen Institute of Technology. + + Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */ + + /* End Header *******************************************************************/ + +#version 450 + +#define MASK_WIDTH 3 +#define HALF_M_WIDTH MASK_WIDTH / 2 +#define SHM_WIDTH 18 +#define NUM_MASKS 8 + +layout(local_size_x = 16, local_size_y = 16) in; +layout(set = 4, binding = 0, rgba8) uniform image2D inputImage; +layout(set = 4, binding = 1, rgba8) uniform image2D resultImage; + +const float kirsch[8][3][3] = { + { + {5, 5, 5}, + {-3, 0, -3}, /*rotation 1 */ + {-3, -3, -3} + }, + { + {5, 5, -3}, + {5, 0, -3}, /*rotation 2 */ + {-3, -3, -3} + }, + { + {5, -3, -3}, + {5, 0, -3}, /*rotation 3 */ + {5, -3, -3} + }, + { + {-3, -3, -3}, + {5, 0, -3}, /*rotation 4 */ + {5, 5, -3} + }, + { + {-3, -3, -3}, + {-3, 0, -3}, /*rotation 5 */ + {5, 5, 5} + }, + { + {-3, -3, -3}, + {-3, 0, 5}, /*rotation 6 */ + {-3, 5, 5} + }, + { + {-3, -3, 5}, + {-3, 0, 5}, /*rotation 7 */ + {-3, -3, 5} + }, + { + {-3, 5, 5}, + {-3, 0, 5}, /*rotation 8 */ + {-3, -3, -3} + } +}; + +vec3 GetImageValues(ivec2 uv, ivec2 inputImageSize) +{ + if (uv.x >= 0 && uv.y >= 0 && uv.x < inputImageSize.x && uv.y < inputImageSize.y) + { + return imageLoad(inputImage, uv).rgb; + } + else + return vec3(0.0f); +} + +//two extra row/col +shared vec3 sData[16 + 2][16 + 2]; + +void main() +{ + // convenient variables + ivec3 globalThread = ivec3(gl_GlobalInvocationID); + ivec3 localThread = ivec3(gl_LocalInvocationID); + ivec2 inputImageSize = imageSize(inputImage); + + // load shared memory + ivec2 start = ivec2(gl_WorkGroupID) * ivec2(gl_WorkGroupSize) - ivec2(HALF_M_WIDTH); + for (int i = localThread.x; i < SHM_WIDTH; i += int(gl_WorkGroupSize.x)) + { + for (int j = localThread.y; j < SHM_WIDTH; j += int(gl_WorkGroupSize.y)) + { + // get from source image (either real values or 0) + vec3 sourceValue = GetImageValues(start + ivec2(i, j), inputImageSize); + sData[i][j] = sourceValue; + } + } + + // wait for shared memory to finish loading + barrier(); + + // max (between all 8 masks) + vec3 maxSum = vec3(0.0f); + + // loop through all masks + for (int i = 0; i < NUM_MASKS; ++i) + { + vec3 sum = vec3(0.0f); + + // start of shared memory + ivec2 shmStart = ivec2(localThread + HALF_M_WIDTH); + for (int j = -1; j < HALF_M_WIDTH + 1; ++j) + { + for (int k = -1; k < HALF_M_WIDTH + 1; ++k) + { + // Perform convolution using shared_memory + sum += sData[shmStart.x + j][shmStart.y + k] * kirsch[i][j + 1][k + 1]; + } + } + + // Get highest sum + maxSum = max(sum, maxSum); + } + + // average the max sum + maxSum = min(max(maxSum / 8, 0), 1.0f); + + // store result into result image + imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(maxSum, 1.0f)); + +} + + + + diff --git a/TempShaderFolder/KirschCs.spv b/TempShaderFolder/KirschCs.spv new file mode 100644 index 0000000000000000000000000000000000000000..1ae5408b12013ad40918e0477191c76630795dbb GIT binary patch literal 5900 zcmZXW37l1R702(ajDQHJ7)Ui}izShWqBRr@VNY^$urZgchR4hUp1fI{nKz+X;8LlW zErzX{Ek?W9YWrkm`(i7$+MX>InQNhazxVx5pWAf#{5a?Q&iY^Oebdr>^(-5o7+iMT@y8fBCu>pUzJs!ktPQ;t43(?H^6S9K zpcl-ghQ4{ZuHDFMp++)jJ;m5?>aNHfR1BBw`sS_&EM*(vz{f3DW-RQU0U^4J8@IQN@6XO4_*D~*lR zM{VjF&oMubX~{Mt&&~C=>^$W7NPTReu`|TBW-o#pEsvFl@|f0a`!supIqS+3<>cRm z94c?`tCL`_E3u>3Zeww{?rYSy4)vvR^Vnf!(M{!qwSv00*jOFK5HMIZ1+ohQL^n(tfy_grsUs`G=3pC znA_|9UBa4u8`KY_XFIYJm~$95FImp%@5Jsv%83PJ9+2~m*qP|s)?31=?ImZ9ID{^~ zKlYi2>;yhXCwqRw%=;XS9=-KD*Mj7ac-QTm3+cKXX>aY~jqQA{+dgZM&MvQiEzIp zB!j;t+4_XMJ--O7ZJsd^|0VS3HC5ohocLmW>)Z;=(O<0d6>RHFB}Ct^V(T+r8T{AK z&6l@c@Lx~7b2@L#`3>|b;5_yT{+sAii3{F2zXhyso-q;sZS<*xV*GdD^ck;=dA^Ho zzIWpuzrUSfoA2*u*v4Nw&E8Y6 zJ(Io3ej4jvi+&PV2QI{3jeKU}p3ZK$H`)=q9{pqxvCl%6Gq!}(Hg-9(2dn^Fv7PVP zi8Izc)sDIw(ESca-P6$JPUEE7k{>x>9>&x}VcX$JF_Bb6FtMAgpotb#Q;}<9H zdFb+I1LyHf<+|~^htCJD$M3TQTqyz!p7_5<9d7b3k=%6p03h%5si{hN^bl~HQ| z-5NL1Z!WR|q0CV&ii86zl*y zfw9(JrR{(qOLas{smBqltm8N5^`Hbcuv^-10B058y5-*pjMX3ChBqZ1@n7!EiEBc} zU3&|wGKHS(Wa?+mLSuKKkE*)US+vcqh6wVjtdxE_VZPAGEIr z)-qS!zI%|-_ua{-wC{V7?*l&eeLvD%W%T_3x;3Kj2hruCul9R@waitI@5qhl?!kNz z^*)3yANEb?t}E`{htZ9Zk2)Vgx6UFEc^^fW5Bp>2&KY$+j&6*6yl0<4-vR8Q-(26v zn}NQl^*wa&T-e`7FV6S_Y&q{w#QYGw*#Ae^a>jTLdy%(+ZoXo-BYy(q>}5UUt#ttM zr$GNz+)3yA8Mqn98zc8~up3;IVt$c0W9_F;&U5vQJsV}r`%CoVymw&B#k~6D%#VBH z8Ebo2t*4B7zd|qW(XX-PqMklE^S$@xdskyUzd?8Auz!p0cVssE<$8Yyn!r)OSpBZk z7=70DTVh>h%=LS8&ob`CAJFAuE`4(5$M?x^NzCy_bbI*SaE?ELI}5lh?f;+QjMX2p ze?jjmAlC9%xLAvM#zoHG(C;cBa{dly&SQc3#>M*eIq!1hKfu0ZuSNb7tOLF52?%MqhdN1z>az4R5fG%g9;2um|Gjao!S0euf%r{=YYaF1j z^V(PceyW@Z{F~ano&$VlffG3E4&>~DejvK%eGoFf6^Epl`N+5fhoZ~hNZq-}!+_iZ za36ISB7OXh>U#u`v$lHFJ{;Zti$K&~j4mIwABiq!ZSPdnQQpH|*#A+$KF)2tJ)ENx z>Ej&6JQ{QY=TMJ1mY_RFag9e{%SX(S=