WIP (TODO: remember to change commit message)

This commit is contained in:
Brandon Mak 2022-10-23 15:05:31 +08:00
parent cc6e2189fa
commit d4fe63722a
35 changed files with 788 additions and 465 deletions

View File

@ -1,16 +1,16 @@
[Window][MainStatusBar] [Window][MainStatusBar]
Pos=0,1060 Pos=0,1367
Size=1920,20 Size=3440,20
Collapsed=0 Collapsed=0
[Window][SHEditorMenuBar] [Window][SHEditorMenuBar]
Pos=0,48 Pos=0,48
Size=1920,1012 Size=3440,1319
Collapsed=0 Collapsed=0
[Window][Hierarchy Panel] [Window][Hierarchy Panel]
Pos=0,142 Pos=0,170
Size=571,918 Size=646,1197
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@ -20,29 +20,29 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1649,48 Pos=3169,48
Size=271,1012 Size=271,1319
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Profiler] [Window][Profiler]
Pos=0,48 Pos=0,48
Size=571,92 Size=646,120
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][Viewport] [Window][Viewport]
Pos=573,48 Pos=648,48
Size=1074,1012 Size=2519,1319
Collapsed=0 Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
[Docking][Data] [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=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=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE 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 DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

View File

@ -10,6 +10,7 @@
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
@ -299,7 +300,7 @@ namespace SHADE
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
return; return;
} }
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout(); bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline()); vkCommandBuffer.bindPipeline(pipelineHdl->GetPipelineBindPoint(), pipelineHdl->GetVkPipeline());
} }
@ -358,9 +359,10 @@ namespace SHADE
} }
} }
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets) void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{ {
vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); uint32_t bindPointIndex = static_cast<uint32_t>(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)); 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<vk::BufferImageCopy>& copyInfo) void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{ {
vkCommandBuffer.copyBufferToImage vkCommandBuffer.copyBufferToImage
@ -500,9 +507,9 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier() // //vkCommandBuffer.pipelineBarrier()
//} //}
void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept
{ {
boundPipelineLayoutHdl = pipelineLayout; bindPointData[static_cast<uint32_t>(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(), auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(), vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
0, 0,
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData); layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
} }
/***************************************************************************/ /***************************************************************************/
@ -695,7 +703,7 @@ namespace SHADE
, usageFlags{ rhs.usageFlags } , usageFlags{ rhs.usageFlags }
, commandBufferCount{ rhs.commandBufferCount } , commandBufferCount{ rhs.commandBufferCount }
, parentPool{ rhs.parentPool } , parentPool{ rhs.parentPool }
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } , bindPointData{ std::move (rhs.bindPointData)}
{ {
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
@ -728,7 +736,7 @@ namespace SHADE
usageFlags = rhs.usageFlags; usageFlags = rhs.usageFlags;
commandBufferCount = rhs.commandBufferCount; commandBufferCount = rhs.commandBufferCount;
parentPool = rhs.parentPool; parentPool = rhs.parentPool;
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl; bindPointData = std::move(rhs.bindPointData);
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
rhs.vkCommandBuffer = VK_NULL_HANDLE; rhs.vkCommandBuffer = VK_NULL_HANDLE;

View File

@ -6,6 +6,7 @@
#include "SHCommandPoolResetMode.h" #include "SHCommandPoolResetMode.h"
#include "Resource/ResourceLibrary.h" #include "Resource/ResourceLibrary.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Pipeline/SHPipelineType.h"
namespace SHADE namespace SHADE
{ {
@ -39,7 +40,14 @@ namespace SHADE
friend class ResourceLibrary<SHVkCommandBuffer>; friend class ResourceLibrary<SHVkCommandBuffer>;
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512; static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
private: private:
struct PipelineBindPointData
{
//! The currently bound pipeline
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
};
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -66,8 +74,8 @@ namespace SHADE
//! The command pool that this command buffer belongs to //! The command pool that this command buffer belongs to
Handle<SHVkCommandPool> parentPool; Handle<SHVkCommandPool> parentPool;
//! The currently bound pipeline //! Every command buffer will have a set of pipeline bind point specific data
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl; std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
//! The push constant data for the command buffer //! The push constant data for the command buffer
uint8_t pushConstantData[PUSH_CONSTANT_SIZE]; uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
@ -112,13 +120,16 @@ namespace SHADE
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept; void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept; void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept; void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets); void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, SH_PIPELINE_TYPE bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
// Draw Commands // Draw Commands
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept; 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 DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount); void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Compute Commands
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
// Buffer Copy // Buffer Copy
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo); void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo); void CopyImageToBuffer (const vk::Image& src, const vk::Buffer& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
@ -138,13 +149,13 @@ namespace SHADE
// Push Constant variable setting // Push Constant variable setting
template <typename T> template <typename T>
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<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); memcpy (static_cast<uint8_t*>(pushConstantData) + bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
}; };
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept; void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout, SH_PIPELINE_TYPE pipelineType) noexcept;
void SubmitPushConstants (void) const noexcept; void SubmitPushConstants (SH_PIPELINE_TYPE bindPoint) const noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */

View File

@ -91,7 +91,7 @@ namespace SHADE
// new write for the binding // new write for the binding
updater.writeInfos.emplace_back(); updater.writeInfos.emplace_back();
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
auto& writeInfo = updater.writeInfos.back(); 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 // 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::eSampler:
//case vk::DescriptorType::eSampledImage: //case vk::DescriptorType::eSampledImage:
case vk::DescriptorType::eCombinedImageSampler: case vk::DescriptorType::eCombinedImageSampler:
case vk::DescriptorType::eStorageImage:
case vk::DescriptorType::eInputAttachment:
writeInfo.descImageInfos.resize(descriptorCount); writeInfo.descImageInfos.resize(descriptorCount);
break; break;
//case vk::DescriptorType::eStorageImage:
// break;
case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer:
case vk::DescriptorType::eUniformBuffer: case vk::DescriptorType::eUniformBuffer:
@ -165,6 +165,7 @@ namespace SHADE
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
{ {
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); 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) for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)

View File

@ -31,6 +31,8 @@ namespace SHADE
class SHVkDescriptorSetGroup class SHVkDescriptorSetGroup
{ {
public: public:
using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -369,7 +369,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) void SHBatch::Draw(Handle<SHVkCommandBuffer> 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."); SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
return; return;
@ -385,7 +385,7 @@ namespace SHADE
cmdBuffer->BindDescriptorSet cmdBuffer->BindDescriptorSet
( (
matPropsDescSet[frameIndex], matPropsDescSet[frameIndex],
vk::PipelineBindPoint::eGraphics, SH_PIPELINE_TYPE::GRAPHICS,
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
dynamicOffset dynamicOffset
); );

View File

@ -20,91 +20,91 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp) SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
: subpass { sp } : subpass{ sp }
{} {}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHSuperBatch::Add(const SHRenderable* renderable) noexcept void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> 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<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); batches.emplace_back(PIPELINE);
batch = batches.end() - 1;
// 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);
} }
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept // Add renderable in
batch->Add(renderable);
}
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> 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<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); batch.Clear();
// 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);
} }
batches.clear();
}
void SHSuperBatch::Clear() noexcept void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{
for (auto& batch : batches)
{ {
for (auto& batch : batches) batch.UpdateMaterialBuffer(frameIndex, descPool);
{ batch.UpdateTransformBuffer(frameIndex);
batch.Clear(); batch.UpdateEIDBuffer(frameIndex);
}
batches.clear();
} }
}
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{ {
for (auto& batch : batches) batch.Build(device, descPool, frameIndex);
{
batch.UpdateMaterialBuffer(frameIndex, descPool);
batch.UpdateTransformBuffer(frameIndex);
batch.UpdateEIDBuffer(frameIndex);
}
} }
}
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{ {
// Build all batches batch.Draw(cmdBuffer, frameIndex);
for (auto& batch : batches)
{
batch.Build(device, descPool, frameIndex);
}
}
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Draw(cmdBuffer, frameIndex);
}
} }
}
} }

View File

@ -123,12 +123,12 @@ namespace SHADE
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true); shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, 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); shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl"); auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
cubeVS->Reflect(); cubeVS->Reflect();
cubeFS->Reflect(); cubeFS->Reflect();
greyscale->Reflect(); greyscale->Reflect();
@ -171,28 +171,25 @@ namespace SHADE
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); 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("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); 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 //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Scene"); gBufferWriteSubpass->AddColorOutput("Scene Pre Postprocess");
gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); 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 // We do this to just transition our scene layout to shader read
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); //auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
sceneLayoutTransitionSubpass->AddInput("Scene"); //sceneLayoutTransitionSubpass->AddGeneralInput("Scene");
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
node->AddNodeCompute (greyscale, {"Scene Pre Postprocess", "Scene"});
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -375,7 +372,7 @@ namespace SHADE
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight()); uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h); currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout()); currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA) for (auto& [buffer, bindingPoint] : MESH_DATA)
@ -395,7 +392,7 @@ namespace SHADE
currentCmdBuffer->BindDescriptorSet currentCmdBuffer->BindDescriptorSet
( (
textureDescSet, textureDescSet,
vk::PipelineBindPoint::eGraphics, SH_PIPELINE_TYPE::GRAPHICS,
0, 0,
texDynamicOffset texDynamicOffset
); );
@ -741,8 +738,8 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR #ifdef SHEDITOR
cameraSystem->GetEditorCamera()->SetWidth(resizeWidth); cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
cameraSystem->GetEditorCamera()->SetHeight(resizeHeight); cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
#else #else
#endif #endif

View File

@ -68,7 +68,7 @@ namespace SHADE
{ {
std::vector combinedImageSampler 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 // 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

View File

@ -82,7 +82,7 @@ namespace SHADE
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; std::array<uint32_t, 1> 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 });
} }
} }

View File

@ -5,9 +5,13 @@ namespace SHADE
{ {
enum class SH_PIPELINE_TYPE enum class SH_PIPELINE_TYPE
{ {
GRAPHICS, GRAPHICS = 0,
COMPUTE, COMPUTE,
RAY_TRACING,
NUM_TYPES,
}; };
} }
#endif #endif

View File

@ -4,6 +4,7 @@
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Debugging/SHVulkanDebugUtil.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -268,7 +269,7 @@ namespace SHADE
, logicalDeviceHdl{ rhs.logicalDeviceHdl } , logicalDeviceHdl{ rhs.logicalDeviceHdl }
, pipelineLayout { rhs.pipelineLayout } , pipelineLayout { rhs.pipelineLayout }
{ {
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
} }
/***************************************************************************/ /***************************************************************************/
@ -308,7 +309,8 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHVkPipeline::~SHVkPipeline(void) noexcept 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; created = rhs.created;
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
return *this; return *this;
} }
@ -422,18 +424,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
{ {
switch (pipelineType) return SHVkUtil::GetPipelineBindPointFromType(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;
}
} }
/***************************************************************************/ /***************************************************************************/
@ -473,4 +464,9 @@ namespace SHADE
return pipelineLayout; return pipelineLayout;
} }
SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
{
return pipelineType;
}
} }

View File

@ -77,6 +77,7 @@ namespace SHADE
vk::Pipeline GetVkPipeline (void) const noexcept; vk::Pipeline GetVkPipeline (void) const noexcept;
bool GetIsCreated (void) const noexcept; bool GetIsCreated (void) const noexcept;
Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept; Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept;
SH_PIPELINE_TYPE GetPipelineType (void) const noexcept;
}; };
} }

View File

@ -216,9 +216,18 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
{ {
// pipeline layouts contain global layouts first, then layouts for allocation
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size()); 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()); vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
for (auto const& layout : descriptorSetLayoutsAllocate) for (auto const& layout : descriptorSetLayoutsAllocate)
{ {
@ -226,18 +235,13 @@ namespace SHADE
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle()); vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
} }
// pipeline layouts contain global layouts first, then layouts for allocation for (auto const& layout : descriptorSetLayoutsPipeline)
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
// First we insert the global layouts
for (auto const& layout : descriptorSetLayoutsGlobal)
{ {
descriptorSetLayoutsPipeline.emplace_back(layout);
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle()); vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
} }
// Then we append layouts for allocation at the back of the vector // 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 , descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
, descriptorSetLayoutsAllocate{} , descriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
{ {
for (auto& mod : shaderModules) for (auto& mod : shaderModules)
@ -318,6 +323,7 @@ namespace SHADE
, descriptorSetLayoutsGlobal{} , descriptorSetLayoutsGlobal{}
, descriptorSetLayoutsAllocate{} , descriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsAllocate{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
{ {
@ -368,7 +374,8 @@ namespace SHADE
, descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)} , descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)}
, descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)} , descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)}
, vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)} , 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; rhs.vkPipelineLayout = VK_NULL_HANDLE;
} }
@ -441,12 +448,12 @@ namespace SHADE
return {}; return {};
} }
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
{ {
return descriptorSetLayoutsPipeline; return descriptorSetLayoutsPipeline;
} }
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
{ {
return descriptorSetLayoutsAllocate; return descriptorSetLayoutsAllocate;
} }
@ -464,7 +471,8 @@ namespace SHADE
descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal); descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal);
descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate); descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate);
vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate); 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; rhs.vkPipelineLayout = VK_NULL_HANDLE;

View File

@ -74,12 +74,12 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept; std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept; vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept; SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept; Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsPipeline(void) const noexcept; std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsPipeline(void) const noexcept;
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsAllocate(void) const noexcept; std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsAllocate(void) const noexcept;
}; };
} }

View File

@ -10,7 +10,8 @@ namespace SHADE
DEPTH = 0x04, DEPTH = 0x04,
STENCIL = 0x08, STENCIL = 0x08,
DEPTH_STENCIL = 0x10, DEPTH_STENCIL = 0x10,
INPUT = 0x20 INPUT = 0x20,
STORAGE = 0x40
}; };
} }

View File

@ -10,7 +10,7 @@
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h" #include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpassCompute.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
namespace SHADE namespace SHADE
{ {
@ -59,7 +59,7 @@ namespace SHADE
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format; format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
} }
graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags));
} }
/***************************************************************************/ /***************************************************************************/
@ -104,16 +104,6 @@ namespace SHADE
for (auto& input : subpass->inputReferences) for (auto& input : subpass->inputReferences)
resourceAttFinalLayouts[input.attachment] = input.layout; 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) 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 // 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 // the resources being used. For each resource we want to query the type and record it
// in bit fields (1 bit for each subpass). // 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; uint32_t i = 0;
@ -227,9 +217,6 @@ namespace SHADE
if (subpass->inputReferences.size()) if (subpass->inputReferences.size())
inputDependencies |= (1 << i); 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 // Input attachments can be any type, so we need to check what type it is
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
@ -295,12 +282,6 @@ namespace SHADE
dstAccess |= vk::AccessFlagBits::eInputAttachmentRead; 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 subpass of first renderpass, stage flag should be bottom of pipe
//if (&node == &nodes.front() && i == 0) //if (&node == &nodes.front() && i == 0)
// srcStage = vk::PipelineStageFlagBits::eBottomOfPipe; // srcStage = vk::PipelineStageFlagBits::eBottomOfPipe;
@ -316,8 +297,8 @@ namespace SHADE
dep.srcStageMask = srcStage; dep.srcStageMask = srcStage;
// initialize the barriers // initialize input descriptors
//node->subpasses[i]->InitComputeBarriers(); node->subpasses[i]->CreateInputDescriptors();
} }
} }
} }
@ -371,15 +352,16 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
{ {
resourceManager = std::make_shared<ResourceManager>();
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>(); renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
renderGraphStorage->logicalDevice = logicalDevice; renderGraphStorage->logicalDevice = logicalDevice;
renderGraphStorage->swapchain = swapchain; renderGraphStorage->swapchain = swapchain;
renderGraphStorage->resourceManager = resourceManager; renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
renderGraphStorage->ptrToResources = &graphResources;
} }
/***************************************************************************/ /***************************************************************************/
@ -396,17 +378,14 @@ namespace SHADE
SHRenderGraph::SHRenderGraph(void) noexcept SHRenderGraph::SHRenderGraph(void) noexcept
: renderGraphStorage{} : renderGraphStorage{}
, nodes{} , nodes{}
, graphResources{}
, resourceManager{nullptr} , resourceManager{nullptr}
{ {
resourceManager = std::make_shared<ResourceManager>();
} }
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
: renderGraphStorage{ rhs.renderGraphStorage } : renderGraphStorage{ rhs.renderGraphStorage }
, nodeIndexing{ std::move(rhs.nodeIndexing) } , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) } , nodes{ std::move(rhs.nodes) }
, graphResources{ std::move(rhs.graphResources) }
, resourceManager{ std::move(rhs.resourceManager) } , resourceManager{ std::move(rhs.resourceManager) }
{ {
@ -420,7 +399,6 @@ namespace SHADE
renderGraphStorage = rhs.renderGraphStorage; renderGraphStorage = rhs.renderGraphStorage;
nodeIndexing = std::move(rhs.nodeIndexing); nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes); nodes = std::move(rhs.nodes);
graphResources = std::move(rhs.graphResources);
resourceManager = std::move(rhs.resourceManager); resourceManager = std::move(rhs.resourceManager);
return *this; return *this;
@ -456,12 +434,12 @@ namespace SHADE
for (auto const& instruction : resourceInstruction) for (auto const& instruction : resourceInstruction)
{ {
// If the resource that the new node is requesting for exists, allow the graph to reference it // 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( descInitParams.push_back(
{ {
.resourceHdl = graphResources.at(instruction.resourceName), .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
.dontClearOnLoad = false, .dontClearOnLoad = instruction.dontClearOnLoad,
} }
); );
} }
@ -506,12 +484,31 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Generate(void) noexcept void SHRenderGraph::Generate(void) noexcept
{ {
CheckForNodeComputes();
ConfigureAttachmentDescriptions(); ConfigureAttachmentDescriptions();
ConfigureSubpasses(); ConfigureSubpasses();
ConfigureRenderpasses(); ConfigureRenderpasses();
ConfigureFramebuffers(); 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 // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
@ -531,7 +528,7 @@ namespace SHADE
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{ {
// resize resources // resize resources
for (auto& [name, resource]: graphResources) for (auto& [name, resource] : *renderGraphStorage->graphResources)
resource->HandleResize(newWidth, newHeight); resource->HandleResize(newWidth, newHeight);
for (auto& node : nodes) for (auto& node : nodes)
@ -551,9 +548,9 @@ namespace SHADE
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept Handle<SHRenderGraphResource> 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 {}; return {};
} }

View File

@ -66,9 +66,6 @@ namespace SHADE
//! Render graph nodes //! Render graph nodes
std::vector<Handle<SHRenderGraphNode>> nodes; std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resources that exist for the entire render graph
std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<ResourceManager> resourceManager; std::shared_ptr<ResourceManager> resourceManager;
@ -88,10 +85,11 @@ namespace SHADE
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept; void CheckForNodeComputes (void) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */

View File

@ -7,6 +7,8 @@
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "SHSubpass.h" #include "SHSubpass.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -80,7 +82,6 @@ namespace SHADE
fbHeight = attResources[j]->height; fbHeight = attResources[j]->height;
} }
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
} }
@ -88,6 +89,11 @@ namespace SHADE
{ {
subpass->HandleResize(); subpass->HandleResize();
} }
for (auto& nodeCompute : nodeComputes)
{
nodeCompute->HandleResize();
}
} }
/***************************************************************************/ /***************************************************************************/
@ -121,6 +127,7 @@ namespace SHADE
, subpasses{} , subpasses{}
, executed{ false } , executed{ false }
, configured{ false } , configured{ false }
, nodeComputes{}
{ {
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(graphStorage->logicalDevice); pipelineLibrary.Init(graphStorage->logicalDevice);
@ -181,6 +188,7 @@ namespace SHADE
, batcher{ std::move(rhs.batcher) } , batcher{ std::move(rhs.batcher) }
, spDescs{ std::move(rhs.spDescs) } , spDescs{ std::move(rhs.spDescs) }
, spDeps{ std::move(rhs.spDeps) } , spDeps{ std::move(rhs.spDeps) }
, nodeComputes{ std::move(rhs.nodeComputes) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -204,6 +212,7 @@ namespace SHADE
batcher = std::move(rhs.batcher); batcher = std::move(rhs.batcher);
spDescs = std::move(rhs.spDescs); spDescs = std::move(rhs.spDescs);
spDeps = std::move(rhs.spDeps); spDeps = std::move(rhs.spDeps);
nodeComputes = std::move(rhs.nodeComputes);
rhs.renderpass = {}; rhs.renderpass = {};
@ -235,7 +244,7 @@ namespace SHADE
} }
// Add subpass to container and create mapping for it // Add subpass to container and create mapping for it
subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), subpasses.size(), &resourceAttachmentMapping)); subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*graphStorage->resourceManager); subpass->Init(*graphStorage->resourceManager);
@ -246,21 +255,84 @@ namespace SHADE
return subpass; return subpass;
} }
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
{
// Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> 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<SHRenderGraphNodeCompute>(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<std::string> 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<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{ {
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0; uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
for (uint32_t i = 0; i < subpasses.size(); ++i) for (uint32_t i = 0; i < subpasses.size(); ++i)
{ {
subpasses[i]->Execute(commandBuffer, descPool, frameIndex); subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
// Go to next subpass if not last subpass // Go to next subpass if not last subpass
if (i != subpasses.size() - 1) if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
commandBuffer->NextSubpass(); commandBuffer->NextSubpass();
} }
commandBuffer->EndRenderpass(); commandBuffer->EndRenderpass();
// Execute all subpass computes
for (auto& sbCompute : nodeComputes)
{
sbCompute->Execute(commandBuffer, frameIndex);
}
} }
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept

View File

@ -21,6 +21,7 @@ namespace SHADE
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHRenderGraphStorage; class SHRenderGraphStorage;
class SHRenderGraphNodeCompute;
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode> class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
{ {
@ -67,6 +68,10 @@ namespace SHADE
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass //! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
SHPipelineLibrary pipelineLibrary; 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<Handle<SHRenderGraphNodeCompute>> nodeComputes;
//! Whether or not the node has finished execution //! Whether or not the node has finished execution
bool executed; bool executed;
@ -75,6 +80,7 @@ namespace SHADE
SHBatcher batcher; SHBatcher batcher;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -94,6 +100,9 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept;
void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept; Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;

View File

@ -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<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& 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<uint32_t> variableCounts{ static_cast<uint32_t>(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<SHVkCommandBuffer> 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<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, 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;
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "Resource/Handle.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include <initializer_list>
#include <string>
#include <unordered_set>
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<SHVkPipeline> computePipeline;
//! Pipeline layout for the pipeline creation
Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups;
//! vector of resources needed by the subpass compute
std::vector<Handle<SHRenderGraphResource>> 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<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept;
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
friend class SHRenderGraph;
friend class SHRenderGraphNode;
};
}

View File

@ -117,6 +117,9 @@ namespace SHADE
usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled; usage |= vk::ImageUsageFlagBits::eSampled;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
usage |= vk::ImageUsageFlagBits::eStorage;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT: case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
{ {
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. "); SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
@ -334,4 +337,9 @@ namespace SHADE
return mipLevels; return mipLevels;
} }
std::string SHRenderGraphResource::GetName(void) const noexcept
{
return resourceName;
}
} }

View File

@ -88,9 +88,11 @@ namespace SHADE
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
uint8_t GetMipLevels (void) const noexcept; uint8_t GetMipLevels (void) const noexcept;
std::string GetName (void) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass; friend class SHSubpass;
friend class SHRenderGraphNodeCompute;
}; };
} }

View File

@ -9,13 +9,14 @@ namespace SHADE
class SHVkSwapchain; class SHVkSwapchain;
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHRenderGraphResource;
class SHRenderGraphStorage class SHRenderGraphStorage
{ {
//! Logical device for creation of vulkan objects //! Logical device for creation of vulkan objects
Handle<SHVkLogicalDevice> logicalDevice; Handle<SHVkLogicalDevice> logicalDevice;
//! swapchain hdl //! swapchain handle
Handle<SHVkSwapchain> swapchain; Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects //! Resource manager for creation of objects
@ -24,13 +25,19 @@ namespace SHADE
//! Descriptor pool for the descriptor sets to be created in the subpasses //! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool; Handle<SHVkDescriptorPool> descriptorPool;
//! For accessing resources anyone in the graph //! For accessing resources anywhere in the graph
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources; Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
//SHRenderGraphStorage(void) noexcept;
//SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHSubpass; friend class SHSubpass;
friend class SHRenderGraphResource; friend class SHRenderGraphResource;
friend class SHSubpassCompute; friend class SHRenderGraphNodeCompute;
}; };
} }

View File

@ -7,7 +7,6 @@
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "SHRenderGraphNode.h" #include "SHRenderGraphNode.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpassCompute.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkSampler.h" #include "Graphics/Images/SHVkSampler.h"
@ -40,7 +39,6 @@ namespace SHADE
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
, graphStorage{ renderGraphStorage } , graphStorage{ renderGraphStorage }
, subpassComputes{}
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS} , inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
{ {
} }
@ -66,8 +64,12 @@ namespace SHADE
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping } , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, descriptorSetLayout{ rhs.descriptorSetLayout } , descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) } , exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
, graphStorage{ std::move(rhs.graphStorage) } , graphStorage{ rhs.graphStorage }
, subpassComputes{std::move (rhs.subpassComputes)} , 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; resourceAttachmentMapping = rhs.resourceAttachmentMapping;
descriptorSetLayout = rhs.descriptorSetLayout; descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = std::move(rhs.graphStorage); graphStorage = rhs.graphStorage;
subpassComputes = std::move(rhs.subpassComputes); inputNames = std::move(rhs.inputNames);
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
inputDescriptorLayout = rhs.inputDescriptorLayout;
inputSamplers = rhs.inputSamplers;
return *this; return *this;
} }
@ -117,7 +122,12 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept 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 //Invalid
return; 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 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); inputNames.push_back(resourceToReference);
} }
void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept 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<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@ -196,11 +211,6 @@ namespace SHADE
drawCall(commandBuffer); drawCall(commandBuffer);
} }
// if there are subpass computes, transition all to GENERAL layout first
for (auto& sbCompute : subpassComputes)
{
}
} }
void SHSubpass::HandleResize(void) noexcept void SHSubpass::HandleResize(void) noexcept
@ -213,29 +223,6 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall); exteriorDrawCalls.push_back(newDrawCall);
} }
Handle<SHSubpassCompute> SHSubpass::AddSubpassCompute(Handle<SHVkShaderModule> computeShaderModule/*, std::initializer_list<std::string> resources*/) noexcept
{
//// for the subpass compute to store indices to the resources, see member comments
//std::unordered_set<uint32_t> attDescIndices{};
//attDescIndices.reserve (resources.size());
//// Look for the required resources in the graph
//std::vector<Handle<SHRenderGraphResource>> 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<SHSubpassCompute>(graphStorage, computeShaderModule/*, std::move(subpassComputeResources), std::move (attDescIndices)*/);
subpassComputes.push_back(subpassCompute);
return subpassCompute;
}
void SHSubpass::Init(ResourceManager& resourceManager) noexcept void SHSubpass::Init(ResourceManager& resourceManager) noexcept
{ {
@ -245,48 +232,51 @@ namespace SHADE
void SHSubpass::CreateInputDescriptors(void) noexcept void SHSubpass::CreateInputDescriptors(void) noexcept
{ {
//std::vector<SHVkDescriptorSetLayout::Binding> bindings{}; if (inputNames.empty())
return;
//for (auto& input : inputReferences) std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
//{
// 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<uint32_t>(bindings.size()),
// .DescriptorCount = 1,
// .flags = {},
// };
// 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<uint32_t>(bindings.size()),
.DescriptorCount = 1,
.flags = {},
};
//// We build a new descriptor set layout to store our images bindings.push_back(newBinding);
//inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings); }
//// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle. // We build a new descriptor set layout to store our images
//for (uint32_t i = 0; i < bindings.size(); ++i) inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
//{
// 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); // 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)
// else {
// { if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
// inputSamplers.push_back({}); {
// } 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? //// maybe do this in handle resize?
//UpdateWriteDescriptors(); //UpdateWriteDescriptors();
@ -294,39 +284,43 @@ namespace SHADE
void SHSubpass::UpdateWriteDescriptors(void) noexcept void SHSubpass::UpdateWriteDescriptors(void) noexcept
{ {
//auto const& bindings = inputDescriptorLayout->GetBindings(); if (inputNames.empty())
return;
//std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(bindings.size()), 0 }; auto const& bindings = inputDescriptorLayout->GetBindings();
//uint32_t i = 0; std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(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) group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
// {
// // get the resource
// auto resource = graphStorage->ptrToResources->at(inputNames[binding.BindPoint]);
// // If resource is swapchain image, get the correct image, if not just get 0. uint32_t i = 0;
// uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? 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 // If resource is swapchain image, get the correct image, if not just get 0.
// vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal; uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
// // Update descriptor sets // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
// auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout); vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
// group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
// group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
// }
// ++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 //void SHSubpass::InitComputeBarriers(void) noexcept

View File

@ -17,7 +17,6 @@ namespace SHADE
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHRenderGraphStorage; class SHRenderGraphStorage;
class SHSubpassCompute;
class SHVkShaderModule; class SHVkShaderModule;
class SHVkSampler; class SHVkSampler;
@ -64,9 +63,6 @@ namespace SHADE
std::vector<Handle<SHVkSampler>> inputSamplers; std::vector<Handle<SHVkSampler>> inputSamplers;
//! Sometimes we want the subpass to do something to the images instead
//! of drawing objects on the image (i.e. compute).
std::vector<Handle<SHSubpassCompute>> subpassComputes;
////! subpass compute image barriers. We do this because every frame has a different ////! 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, ////! swapchain image. If the resource we want to transition is not a swapchain image,
@ -96,7 +92,9 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Preparation functions // Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept; 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 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 AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept; void AddGeneralInput (std::string resourceToReference) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept; void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
@ -105,7 +103,6 @@ namespace SHADE
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept; void HandleResize (void) noexcept;
Handle<SHSubpassCompute> AddSubpassCompute(Handle<SHVkShaderModule> computeShaderModule/*, std::initializer_list<std::string> resources*/) noexcept;
void Init(ResourceManager& resourceManager) noexcept; void Init(ResourceManager& resourceManager) noexcept;

View File

@ -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<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule/*, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<uint32_t>&& 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<uint32_t> variableCounts{ static_cast<uint32_t>(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
}

View File

@ -1,49 +0,0 @@
#pragma once
#include "Resource/Handle.h"
#include <initializer_list>
#include <string>
#include <unordered_set>
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<SHVkPipeline> pipeline;
//! Pipeline layout for the pipeline creation
Handle<SHVkPipelineLayout> pipelineLayout;
////! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
//Handle<SHVkDescriptorSetGroup> descSetGroup;
////! Required resources to be used in the descriptors
//std::vector<std::string> resourcesRequired;
////! vector of resources needed by the subpass compute
//std::vector<Handle<SHRenderGraphResource>> 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<uint32_t> attachmentDescriptionIndices{};
public:
SHSubpassCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule/*, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<uint32_t>&& attDescIndices*/) noexcept;
//void ExecuteSubpass (void) noexcept;
friend class SHRenderGraph;
friend class SHSubpass;
};
}

View File

@ -55,6 +55,21 @@ namespace SHADE
return 0; 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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{ {
if (bufferHandle) if (bufferHandle)

View File

@ -4,6 +4,7 @@
#include "SHVulkanIncludes.h" #include "SHVulkanIncludes.h"
#include "Resource/Handle.h" #include "Resource/Handle.h"
#include "Graphics/Pipeline/SHPipelineType.h"
namespace SHADE namespace SHADE
{ {
@ -20,10 +21,11 @@ namespace SHADE
class SHVkUtil class SHVkUtil
{ {
public: public:
static bool IsDepthOnlyFormat (vk::Format format) noexcept; static bool IsDepthOnlyFormat (vk::Format format) noexcept;
static bool IsDepthStencilAttachment (vk::Format format) noexcept; static bool IsDepthStencilAttachment (vk::Format format) noexcept;
static bool IsBlendCompatible (vk::Format format) noexcept; static bool IsBlendCompatible (vk::Format format) noexcept;
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept; static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept;
/***********************************************************************************/ /***********************************************************************************/
/*! /*!

View File

@ -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));
}

Binary file not shown.

View File

@ -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));
}

Binary file not shown.