WIP (TODO: remember to change commit message)
This commit is contained in:
parent
cc6e2189fa
commit
d4fe63722a
|
@ -1,16 +1,16 @@
|
|||
[Window][MainStatusBar]
|
||||
Pos=0,1060
|
||||
Size=1920,20
|
||||
Pos=0,1367
|
||||
Size=3440,20
|
||||
Collapsed=0
|
||||
|
||||
[Window][SHEditorMenuBar]
|
||||
Pos=0,48
|
||||
Size=1920,1012
|
||||
Size=3440,1319
|
||||
Collapsed=0
|
||||
|
||||
[Window][Hierarchy Panel]
|
||||
Pos=0,142
|
||||
Size=571,918
|
||||
Pos=0,170
|
||||
Size=646,1197
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
|
@ -20,29 +20,29 @@ Size=400,400
|
|||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=1649,48
|
||||
Size=271,1012
|
||||
Pos=3169,48
|
||||
Size=271,1319
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=0,48
|
||||
Size=571,92
|
||||
Size=646,120
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=573,48
|
||||
Size=1074,1012
|
||||
Pos=648,48
|
||||
Size=2519,1319
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=3440,1319 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=571,1036 Split=Y Selected=0x1E6EB881
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=646,1036 Split=Y Selected=0x1E6EB881
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1074,1036 CentralNode=1 Selected=0x13926F0B
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=999,1036 CentralNode=1 Selected=0x13926F0B
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -299,7 +300,7 @@ namespace SHADE
|
|||
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
|
||||
return;
|
||||
}
|
||||
boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
||||
bindPointData[static_cast<uint32_t>(pipelineHdl->GetPipelineType())].boundPipelineLayoutHdl = pipelineHdl->GetPipelineLayout();
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
vkCommandBuffer.copyBufferToImage
|
||||
|
@ -500,9 +507,9 @@ namespace SHADE
|
|||
// //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(),
|
||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
||||
auto layoutHdl = bindPointData[static_cast<uint32_t>(bindPoint)].boundPipelineLayoutHdl;
|
||||
vkCommandBuffer.pushConstants(layoutHdl->GetVkPipelineLayout(),
|
||||
layoutHdl->GetPushConstantInterface().GetShaderStageFlags(),
|
||||
0,
|
||||
boundPipelineLayoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
||||
layoutHdl->GetPushConstantInterface().GetSize(), pushConstantData);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -695,7 +703,7 @@ namespace SHADE
|
|||
, usageFlags{ rhs.usageFlags }
|
||||
, commandBufferCount{ rhs.commandBufferCount }
|
||||
, parentPool{ rhs.parentPool }
|
||||
, boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
|
||||
, bindPointData{ std::move (rhs.bindPointData)}
|
||||
{
|
||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||
|
||||
|
@ -728,7 +736,7 @@ namespace SHADE
|
|||
usageFlags = rhs.usageFlags;
|
||||
commandBufferCount = rhs.commandBufferCount;
|
||||
parentPool = rhs.parentPool;
|
||||
boundPipelineLayoutHdl = rhs.boundPipelineLayoutHdl;
|
||||
bindPointData = std::move(rhs.bindPointData);
|
||||
memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
|
||||
|
||||
rhs.vkCommandBuffer = VK_NULL_HANDLE;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "SHCommandPoolResetMode.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
|
||||
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -39,7 +40,14 @@ namespace SHADE
|
|||
friend class ResourceLibrary<SHVkCommandBuffer>;
|
||||
|
||||
static constexpr uint16_t PUSH_CONSTANT_SIZE = 512;
|
||||
|
||||
private:
|
||||
struct PipelineBindPointData
|
||||
{
|
||||
//! The currently bound pipeline
|
||||
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -66,8 +74,8 @@ namespace SHADE
|
|||
//! The command pool that this command buffer belongs to
|
||||
Handle<SHVkCommandPool> parentPool;
|
||||
|
||||
//! The currently bound pipeline
|
||||
Handle<SHVkPipelineLayout> boundPipelineLayoutHdl;
|
||||
//! Every command buffer will have a set of pipeline bind point specific data
|
||||
std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
|
||||
|
||||
//! The push constant data for the command buffer
|
||||
uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
|
||||
|
@ -112,13 +120,16 @@ namespace SHADE
|
|||
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) 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 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
|
||||
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
|
||||
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
|
||||
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
|
||||
|
||||
// Compute Commands
|
||||
void ComputeDispatch (uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) noexcept;
|
||||
|
||||
// Buffer Copy
|
||||
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<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
|
||||
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 */
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace SHADE
|
|||
|
||||
// new write for the binding
|
||||
updater.writeInfos.emplace_back();
|
||||
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1);
|
||||
updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
|
||||
auto& writeInfo = updater.writeInfos.back();
|
||||
|
||||
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
|
||||
|
@ -102,10 +102,10 @@ namespace SHADE
|
|||
//case vk::DescriptorType::eSampler:
|
||||
//case vk::DescriptorType::eSampledImage:
|
||||
case vk::DescriptorType::eCombinedImageSampler:
|
||||
case vk::DescriptorType::eStorageImage:
|
||||
case vk::DescriptorType::eInputAttachment:
|
||||
writeInfo.descImageInfos.resize(descriptorCount);
|
||||
break;
|
||||
//case vk::DescriptorType::eStorageImage:
|
||||
// break;
|
||||
case vk::DescriptorType::eUniformTexelBuffer:
|
||||
case vk::DescriptorType::eStorageTexelBuffer:
|
||||
case vk::DescriptorType::eUniformBuffer:
|
||||
|
@ -165,6 +165,7 @@ namespace SHADE
|
|||
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
|
||||
{
|
||||
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace SHADE
|
|||
class SHVkDescriptorSetGroup
|
||||
{
|
||||
public:
|
||||
using viewSamplerLayout = std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructor/Destructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -385,7 +385,7 @@ namespace SHADE
|
|||
cmdBuffer->BindDescriptorSet
|
||||
(
|
||||
matPropsDescSet[frameIndex],
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
SH_PIPELINE_TYPE::GRAPHICS,
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
dynamicOffset
|
||||
);
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
|
||||
: subpass { sp }
|
||||
: subpass{ sp }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -123,12 +123,12 @@ namespace SHADE
|
|||
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
|
||||
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
|
||||
|
||||
shaderSourceLibrary.LoadShader(2, "GreyscaleCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||
shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true);
|
||||
|
||||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||
auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl");
|
||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||
cubeVS->Reflect();
|
||||
cubeFS->Reflect();
|
||||
greyscale->Reflect();
|
||||
|
@ -171,28 +171,25 @@ namespace SHADE
|
|||
|
||||
// Initialize world render graph
|
||||
worldRenderGraph->Init(device, swapchain);
|
||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second);
|
||||
worldRenderGraph->AddResource("Scene Pre Postprocess", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre Postprocess"}, {}); // no predecessors
|
||||
|
||||
//First subpass to write to G-Buffer
|
||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
||||
gBufferWriteSubpass->AddColorOutput("Scene");
|
||||
gBufferWriteSubpass->AddColorOutput("Scene Pre Postprocess");
|
||||
gBufferWriteSubpass->AddColorOutput("Entity ID");
|
||||
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||
|
||||
auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl");
|
||||
|
||||
auto greyscaleSubpass = node->AddSubpass("Greyscale Subpass");
|
||||
greyscaleSubpass->AddGeneralInput("Scene");
|
||||
greyscaleSubpass->AddSubpassCompute(greyscale);
|
||||
|
||||
|
||||
// We do this to just transition our scene layout to shader read
|
||||
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
|
||||
sceneLayoutTransitionSubpass->AddInput("Scene");
|
||||
//auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
|
||||
//sceneLayoutTransitionSubpass->AddGeneralInput("Scene");
|
||||
|
||||
auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
|
||||
node->AddNodeCompute (greyscale, {"Scene Pre Postprocess", "Scene"});
|
||||
|
||||
// Generate world render graph
|
||||
worldRenderGraph->Generate();
|
||||
|
@ -375,7 +372,7 @@ namespace SHADE
|
|||
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
|
||||
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
|
||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||
|
@ -395,7 +392,7 @@ namespace SHADE
|
|||
currentCmdBuffer->BindDescriptorSet
|
||||
(
|
||||
textureDescSet,
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
SH_PIPELINE_TYPE::GRAPHICS,
|
||||
0,
|
||||
texDynamicOffset
|
||||
);
|
||||
|
@ -741,8 +738,8 @@ namespace SHADE
|
|||
|
||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
#ifdef SHEDITOR
|
||||
cameraSystem->GetEditorCamera()->SetWidth(resizeWidth);
|
||||
cameraSystem->GetEditorCamera()->SetHeight(resizeHeight);
|
||||
cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
|
||||
cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace SHADE
|
|||
{
|
||||
std::vector combinedImageSampler
|
||||
{
|
||||
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal),
|
||||
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
|
||||
};
|
||||
|
||||
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace SHADE
|
|||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,13 @@ namespace SHADE
|
|||
{
|
||||
enum class SH_PIPELINE_TYPE
|
||||
{
|
||||
GRAPHICS,
|
||||
GRAPHICS = 0,
|
||||
COMPUTE,
|
||||
RAY_TRACING,
|
||||
NUM_TYPES,
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/Debugging/SHVulkanDebugUtil.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -268,7 +269,7 @@ namespace SHADE
|
|||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
||||
, pipelineLayout { rhs.pipelineLayout }
|
||||
{
|
||||
vkPipeline = VK_NULL_HANDLE;
|
||||
rhs.vkPipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -308,6 +309,7 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
SHVkPipeline::~SHVkPipeline(void) noexcept
|
||||
{
|
||||
if (vkPipeline)
|
||||
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
|
||||
}
|
||||
|
||||
|
@ -336,7 +338,7 @@ namespace SHADE
|
|||
created = rhs.created;
|
||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
||||
|
||||
vkPipeline = VK_NULL_HANDLE;
|
||||
rhs.vkPipeline = VK_NULL_HANDLE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -422,18 +424,7 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
|
||||
{
|
||||
switch (pipelineType)
|
||||
{
|
||||
case SH_PIPELINE_TYPE::GRAPHICS:
|
||||
return vk::PipelineBindPoint::eGraphics;
|
||||
case SH_PIPELINE_TYPE::COMPUTE:
|
||||
return vk::PipelineBindPoint::eCompute;
|
||||
break;
|
||||
default:
|
||||
return vk::PipelineBindPoint::eGraphics;
|
||||
break;
|
||||
|
||||
}
|
||||
return SHVkUtil::GetPipelineBindPointFromType(pipelineType);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -473,4 +464,9 @@ namespace SHADE
|
|||
return pipelineLayout;
|
||||
}
|
||||
|
||||
SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
|
||||
{
|
||||
return pipelineType;
|
||||
}
|
||||
|
||||
}
|
|
@ -77,6 +77,7 @@ namespace SHADE
|
|||
vk::Pipeline GetVkPipeline (void) const noexcept;
|
||||
bool GetIsCreated (void) const noexcept;
|
||||
Handle<SHVkPipelineLayout> GetPipelineLayout (void) const noexcept;
|
||||
SH_PIPELINE_TYPE GetPipelineType (void) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -216,9 +216,18 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
|
||||
{
|
||||
// pipeline layouts contain global layouts first, then layouts for allocation
|
||||
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||
|
||||
// Settle allocate layouts first
|
||||
// First we insert the global layouts
|
||||
for (auto const& layout : descriptorSetLayoutsGlobal)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
//vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
// Then the allocate layouts
|
||||
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
|
||||
for (auto const& layout : descriptorSetLayoutsAllocate)
|
||||
{
|
||||
|
@ -226,18 +235,13 @@ namespace SHADE
|
|||
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
// pipeline layouts contain global layouts first, then layouts for allocation
|
||||
vkDescriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||
|
||||
// First we insert the global layouts
|
||||
for (auto const& layout : descriptorSetLayoutsGlobal)
|
||||
for (auto const& layout : descriptorSetLayoutsPipeline)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
// Then we append layouts for allocation at the back of the vector
|
||||
std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
||||
//std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -294,6 +298,7 @@ namespace SHADE
|
|||
, descriptorSetLayoutsGlobal{pipelineLayoutParams.globalDescSetLayouts } // do a copy, some other pipeline layout might need this
|
||||
, descriptorSetLayoutsAllocate{}
|
||||
, vkDescriptorSetLayoutsAllocate{}
|
||||
, descriptorSetLayoutsPipeline{}
|
||||
, vkDescriptorSetLayoutsPipeline{}
|
||||
{
|
||||
for (auto& mod : shaderModules)
|
||||
|
@ -318,6 +323,7 @@ namespace SHADE
|
|||
, descriptorSetLayoutsGlobal{}
|
||||
, descriptorSetLayoutsAllocate{}
|
||||
, vkDescriptorSetLayoutsAllocate{}
|
||||
, descriptorSetLayoutsPipeline{}
|
||||
, vkDescriptorSetLayoutsPipeline{}
|
||||
|
||||
{
|
||||
|
@ -368,7 +374,8 @@ namespace SHADE
|
|||
, descriptorSetLayoutsGlobal {std::move (rhs.descriptorSetLayoutsGlobal)}
|
||||
, descriptorSetLayoutsAllocate {std::move (rhs.descriptorSetLayoutsAllocate)}
|
||||
, vkDescriptorSetLayoutsAllocate{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
|
||||
, vkDescriptorSetLayoutsPipeline{std::move (rhs.vkDescriptorSetLayoutsAllocate)}
|
||||
, descriptorSetLayoutsPipeline { std::move(rhs.descriptorSetLayoutsPipeline) }
|
||||
, vkDescriptorSetLayoutsPipeline{ std::move(rhs.vkDescriptorSetLayoutsPipeline) }
|
||||
{
|
||||
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
||||
}
|
||||
|
@ -441,12 +448,12 @@ namespace SHADE
|
|||
return {};
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsPipeline;
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsAllocate;
|
||||
}
|
||||
|
@ -464,7 +471,8 @@ namespace SHADE
|
|||
descriptorSetLayoutsGlobal = std::move(rhs.descriptorSetLayoutsGlobal);
|
||||
descriptorSetLayoutsAllocate = std::move(rhs.descriptorSetLayoutsAllocate);
|
||||
vkDescriptorSetLayoutsAllocate = std::move(rhs.vkDescriptorSetLayoutsAllocate);
|
||||
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsAllocate);
|
||||
descriptorSetLayoutsPipeline = std::move(rhs.descriptorSetLayoutsPipeline);
|
||||
vkDescriptorSetLayoutsPipeline = std::move(rhs.vkDescriptorSetLayoutsPipeline);
|
||||
|
||||
rhs.vkPipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ namespace SHADE
|
|||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||
SHPushConstantInterface const& GetPushConstantInterface (void) 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>> GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsPipeline(void) const noexcept;
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ namespace SHADE
|
|||
DEPTH = 0x04,
|
||||
STENCIL = 0x08,
|
||||
DEPTH_STENCIL = 0x10,
|
||||
INPUT = 0x20
|
||||
INPUT = 0x20,
|
||||
STORAGE = 0x40
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "Tools/SHLogger.h"
|
||||
#include "SHAttachmentDescInitParams.h"
|
||||
#include "SHRenderGraphStorage.h"
|
||||
#include "Graphics/RenderGraph/SHSubpassCompute.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ namespace SHADE
|
|||
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
|
||||
}
|
||||
|
||||
graphResources.try_emplace(resourceName, resourceManager->Create<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)
|
||||
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||
|
||||
// Go through all subpass computes and initialize final layouts to GENERAL when a resource is detected to be used in it
|
||||
//for (auto sbCompute : subpass->subpassComputes)
|
||||
//{
|
||||
// auto const& indices = sbCompute->attachmentDescriptionIndices;
|
||||
// for (auto& index : indices)
|
||||
// {
|
||||
// resourceAttFinalLayouts[index] = vk::ImageLayout::eGeneral;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
|
||||
|
@ -188,7 +178,7 @@ namespace SHADE
|
|||
// Now we want to loop through all attachments in all subpasses in the node and query
|
||||
// the resources being used. For each resource we want to query the type and record it
|
||||
// in bit fields (1 bit for each subpass).
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0, descriptorDependencies = 0;
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
|
@ -227,9 +217,6 @@ namespace SHADE
|
|||
if (subpass->inputReferences.size())
|
||||
inputDependencies |= (1 << i);
|
||||
|
||||
if (!subpass->subpassComputes.empty())
|
||||
descriptorDependencies |= (1 << i);
|
||||
|
||||
// Input attachments can be any type, so we need to check what type it is
|
||||
for (auto& inputAtt : subpass->inputReferences)
|
||||
{
|
||||
|
@ -295,12 +282,6 @@ namespace SHADE
|
|||
dstAccess |= vk::AccessFlagBits::eInputAttachmentRead;
|
||||
}
|
||||
|
||||
if (descriptorDependencies & (1 << i))
|
||||
{
|
||||
dstStage |= vk::PipelineStageFlagBits::eComputeShader;
|
||||
dstAccess |= vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eShaderRead;
|
||||
}
|
||||
|
||||
//// If subpass of first renderpass, stage flag should be bottom of pipe
|
||||
//if (&node == &nodes.front() && i == 0)
|
||||
// srcStage = vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||
|
@ -316,8 +297,8 @@ namespace SHADE
|
|||
|
||||
dep.srcStageMask = srcStage;
|
||||
|
||||
// initialize the barriers
|
||||
//node->subpasses[i]->InitComputeBarriers();
|
||||
// initialize input descriptors
|
||||
node->subpasses[i]->CreateInputDescriptors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,15 +352,16 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
|
||||
{
|
||||
resourceManager = std::make_shared<ResourceManager>();
|
||||
|
||||
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
|
||||
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
|
||||
|
||||
renderGraphStorage->logicalDevice = logicalDevice;
|
||||
renderGraphStorage->swapchain = swapchain;
|
||||
|
||||
renderGraphStorage->resourceManager = resourceManager;
|
||||
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
|
||||
|
||||
renderGraphStorage->ptrToResources = &graphResources;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -396,17 +378,14 @@ namespace SHADE
|
|||
SHRenderGraph::SHRenderGraph(void) noexcept
|
||||
: renderGraphStorage{}
|
||||
, nodes{}
|
||||
, graphResources{}
|
||||
, resourceManager{nullptr}
|
||||
{
|
||||
resourceManager = std::make_shared<ResourceManager>();
|
||||
}
|
||||
|
||||
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
|
||||
: renderGraphStorage{ rhs.renderGraphStorage }
|
||||
, nodeIndexing{ std::move(rhs.nodeIndexing) }
|
||||
, nodes{ std::move(rhs.nodes) }
|
||||
, graphResources{ std::move(rhs.graphResources) }
|
||||
, resourceManager{ std::move(rhs.resourceManager) }
|
||||
{
|
||||
|
||||
|
@ -420,7 +399,6 @@ namespace SHADE
|
|||
renderGraphStorage = rhs.renderGraphStorage;
|
||||
nodeIndexing = std::move(rhs.nodeIndexing);
|
||||
nodes = std::move(rhs.nodes);
|
||||
graphResources = std::move(rhs.graphResources);
|
||||
resourceManager = std::move(rhs.resourceManager);
|
||||
|
||||
return *this;
|
||||
|
@ -456,12 +434,12 @@ namespace SHADE
|
|||
for (auto const& instruction : resourceInstruction)
|
||||
{
|
||||
// If the resource that the new node is requesting for exists, allow the graph to reference it
|
||||
if (graphResources.contains(instruction.resourceName))
|
||||
if (renderGraphStorage->graphResources->contains(instruction.resourceName))
|
||||
{
|
||||
descInitParams.push_back(
|
||||
{
|
||||
.resourceHdl = graphResources.at(instruction.resourceName),
|
||||
.dontClearOnLoad = false,
|
||||
.resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
|
||||
.dontClearOnLoad = instruction.dontClearOnLoad,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -506,12 +484,31 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHRenderGraph::Generate(void) noexcept
|
||||
{
|
||||
CheckForNodeComputes();
|
||||
ConfigureAttachmentDescriptions();
|
||||
ConfigureSubpasses();
|
||||
ConfigureRenderpasses();
|
||||
ConfigureFramebuffers();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function goes through all renderpasses and checks for existence of
|
||||
node computes. If they exist, adds dummy subpasses to transition resources
|
||||
into general.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraph::CheckForNodeComputes(void) noexcept
|
||||
{
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
node->AddDummySubpassIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
||||
// better way to manage these
|
||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
|
@ -531,7 +528,7 @@ namespace SHADE
|
|||
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
|
||||
{
|
||||
// resize resources
|
||||
for (auto& [name, resource]: graphResources)
|
||||
for (auto& [name, resource] : *renderGraphStorage->graphResources)
|
||||
resource->HandleResize(newWidth, newHeight);
|
||||
|
||||
for (auto& node : nodes)
|
||||
|
@ -551,9 +548,9 @@ namespace SHADE
|
|||
|
||||
Handle<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 {};
|
||||
}
|
||||
|
|
|
@ -66,9 +66,6 @@ namespace SHADE
|
|||
//! Render graph 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
|
||||
std::shared_ptr<ResourceManager> resourceManager;
|
||||
|
||||
|
@ -89,8 +86,9 @@ namespace SHADE
|
|||
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
|
||||
|
||||
void Generate (void) noexcept;
|
||||
void CheckForNodeComputes (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "SHRenderGraphResource.h"
|
||||
#include "SHSubpass.h"
|
||||
#include "SHRenderGraphStorage.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -80,7 +82,6 @@ namespace SHADE
|
|||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
|
||||
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
|
@ -88,6 +89,11 @@ namespace SHADE
|
|||
{
|
||||
subpass->HandleResize();
|
||||
}
|
||||
|
||||
for (auto& nodeCompute : nodeComputes)
|
||||
{
|
||||
nodeCompute->HandleResize();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -121,6 +127,7 @@ namespace SHADE
|
|||
, subpasses{}
|
||||
, executed{ false }
|
||||
, configured{ false }
|
||||
, nodeComputes{}
|
||||
{
|
||||
// pipeline library initialization
|
||||
pipelineLibrary.Init(graphStorage->logicalDevice);
|
||||
|
@ -181,6 +188,7 @@ namespace SHADE
|
|||
, batcher{ std::move(rhs.batcher) }
|
||||
, spDescs{ std::move(rhs.spDescs) }
|
||||
, spDeps{ std::move(rhs.spDeps) }
|
||||
, nodeComputes{ std::move(rhs.nodeComputes) }
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
|
@ -204,6 +212,7 @@ namespace SHADE
|
|||
batcher = std::move(rhs.batcher);
|
||||
spDescs = std::move(rhs.spDescs);
|
||||
spDeps = std::move(rhs.spDeps);
|
||||
nodeComputes = std::move(rhs.nodeComputes);
|
||||
|
||||
|
||||
rhs.renderpass = {};
|
||||
|
@ -235,7 +244,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Add subpass to container and create mapping for it
|
||||
subpasses.emplace_back(graphStorage->resourceManager->Create<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);
|
||||
Handle<SHSubpass> subpass = subpasses.back();
|
||||
subpass->Init(*graphStorage->resourceManager);
|
||||
|
@ -246,21 +255,84 @@ namespace SHADE
|
|||
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
|
||||
{
|
||||
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]);
|
||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||
|
||||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
{
|
||||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != subpasses.size() - 1)
|
||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace SHADE
|
|||
class SHVkDescriptorPool;
|
||||
class SHGraphicsGlobalData;
|
||||
class SHRenderGraphStorage;
|
||||
class SHRenderGraphNodeCompute;
|
||||
|
||||
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
|
||||
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
|
||||
bool executed;
|
||||
|
||||
|
@ -75,6 +80,7 @@ namespace SHADE
|
|||
|
||||
SHBatcher batcher;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -94,6 +100,9 @@ namespace SHADE
|
|||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
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()
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
@ -117,6 +117,9 @@ namespace SHADE
|
|||
usage |= vk::ImageUsageFlagBits::eInputAttachment;
|
||||
usage |= vk::ImageUsageFlagBits::eSampled;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
|
||||
usage |= vk::ImageUsageFlagBits::eStorage;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
|
||||
{
|
||||
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
|
||||
|
@ -334,4 +337,9 @@ namespace SHADE
|
|||
return mipLevels;
|
||||
}
|
||||
|
||||
std::string SHRenderGraphResource::GetName(void) const noexcept
|
||||
{
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
}
|
|
@ -88,9 +88,11 @@ namespace SHADE
|
|||
Handle<SHVkImageView> GetImageView (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;
|
||||
std::string GetName (void) const noexcept;
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
friend class SHSubpass;
|
||||
friend class SHRenderGraphNodeCompute;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,13 +9,14 @@ namespace SHADE
|
|||
class SHVkSwapchain;
|
||||
class SHGraphicsGlobalData;
|
||||
class SHVkDescriptorPool;
|
||||
class SHRenderGraphResource;
|
||||
|
||||
class SHRenderGraphStorage
|
||||
{
|
||||
//! Logical device for creation of vulkan objects
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
|
||||
//! swapchain hdl
|
||||
//! swapchain handle
|
||||
Handle<SHVkSwapchain> swapchain;
|
||||
|
||||
//! Resource manager for creation of objects
|
||||
|
@ -24,13 +25,19 @@ namespace SHADE
|
|||
//! Descriptor pool for the descriptor sets to be created in the subpasses
|
||||
Handle<SHVkDescriptorPool> descriptorPool;
|
||||
|
||||
//! For accessing resources anyone in the graph
|
||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
||||
//! For accessing resources anywhere in the graph
|
||||
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 SHRenderGraphNode;
|
||||
friend class SHSubpass;
|
||||
friend class SHRenderGraphResource;
|
||||
friend class SHSubpassCompute;
|
||||
friend class SHRenderGraphNodeCompute;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "SHRenderGraphStorage.h"
|
||||
#include "Graphics/RenderGraph/SHSubpassCompute.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
|
@ -40,7 +39,6 @@ namespace SHADE
|
|||
, depthReferences{}
|
||||
, inputReferences{}
|
||||
, graphStorage{ renderGraphStorage }
|
||||
, subpassComputes{}
|
||||
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
|
||||
{
|
||||
}
|
||||
|
@ -66,8 +64,12 @@ namespace SHADE
|
|||
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
||||
, descriptorSetLayout{ rhs.descriptorSetLayout }
|
||||
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
|
||||
, graphStorage{ std::move(rhs.graphStorage) }
|
||||
, subpassComputes{std::move (rhs.subpassComputes)}
|
||||
, graphStorage{ rhs.graphStorage }
|
||||
, inputNames{ std::move(rhs.inputNames) }
|
||||
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
|
||||
, inputDescriptorLayout{ rhs.inputDescriptorLayout }
|
||||
, inputSamplers{ rhs.inputSamplers }
|
||||
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -97,8 +99,11 @@ namespace SHADE
|
|||
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
|
||||
descriptorSetLayout = rhs.descriptorSetLayout;
|
||||
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
|
||||
graphStorage = std::move(rhs.graphStorage);
|
||||
subpassComputes = std::move(rhs.subpassComputes);
|
||||
graphStorage = rhs.graphStorage;
|
||||
inputNames = std::move(rhs.inputNames);
|
||||
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
|
||||
inputDescriptorLayout = rhs.inputDescriptorLayout;
|
||||
inputSamplers = rhs.inputSamplers;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -117,7 +122,12 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
|
||||
{
|
||||
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
||||
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
||||
}
|
||||
|
||||
void SHSubpass::AddGeneralColorOutput(std::string resourceToReference) noexcept
|
||||
{
|
||||
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -154,7 +164,13 @@ namespace SHADE
|
|||
//Invalid
|
||||
return;
|
||||
}
|
||||
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
|
||||
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), imageLayout });
|
||||
}
|
||||
|
||||
void SHSubpass::AddGeneralDepthOutput(std::string resourceToReference) noexcept
|
||||
{
|
||||
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -171,15 +187,14 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHSubpass::AddInput(std::string resourceToReference) noexcept
|
||||
{
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||
|
||||
inputNames.push_back(resourceToReference);
|
||||
}
|
||||
|
||||
void SHSubpass::AddGeneralInput(std::string resourceToReference) noexcept
|
||||
{
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
|
||||
}
|
||||
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
|
@ -196,11 +211,6 @@ namespace SHADE
|
|||
drawCall(commandBuffer);
|
||||
}
|
||||
|
||||
// if there are subpass computes, transition all to GENERAL layout first
|
||||
for (auto& sbCompute : subpassComputes)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SHSubpass::HandleResize(void) noexcept
|
||||
|
@ -213,29 +223,6 @@ namespace SHADE
|
|||
exteriorDrawCalls.push_back(newDrawCall);
|
||||
}
|
||||
|
||||
Handle<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
|
||||
{
|
||||
|
@ -245,48 +232,51 @@ namespace SHADE
|
|||
|
||||
void SHSubpass::CreateInputDescriptors(void) noexcept
|
||||
{
|
||||
//std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
|
||||
if (inputNames.empty())
|
||||
return;
|
||||
|
||||
//for (auto& input : inputReferences)
|
||||
//{
|
||||
// SHVkDescriptorSetLayout::Binding newBinding
|
||||
// {
|
||||
// .Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage,
|
||||
// .Stage = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
|
||||
// .BindPoint = static_cast<uint32_t>(bindings.size()),
|
||||
// .DescriptorCount = 1,
|
||||
// .flags = {},
|
||||
// };
|
||||
std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
|
||||
|
||||
// bindings.push_back(newBinding);
|
||||
//}
|
||||
for (auto& input : inputReferences)
|
||||
{
|
||||
SHVkDescriptorSetLayout::Binding newBinding
|
||||
{
|
||||
.Type = (input.layout == vk::ImageLayout::eShaderReadOnlyOptimal) ? vk::DescriptorType::eInputAttachment : vk::DescriptorType::eStorageImage,
|
||||
.Stage = vk::ShaderStageFlagBits::eFragment,
|
||||
.BindPoint = static_cast<uint32_t>(bindings.size()),
|
||||
.DescriptorCount = 1,
|
||||
.flags = {},
|
||||
};
|
||||
|
||||
//// We build a new descriptor set layout to store our images
|
||||
//inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
|
||||
bindings.push_back(newBinding);
|
||||
}
|
||||
|
||||
//// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle.
|
||||
//for (uint32_t i = 0; i < bindings.size(); ++i)
|
||||
//{
|
||||
// if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
|
||||
// {
|
||||
// auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams
|
||||
// {
|
||||
// .minFilter = vk::Filter::eLinear,
|
||||
// .magFilter = vk::Filter::eLinear,
|
||||
// .addressMode = vk::SamplerAddressMode::eRepeat,
|
||||
// .mipmapMode = vk::SamplerMipmapMode::eLinear,
|
||||
// .minLod = -1000,
|
||||
// .maxLod = 1000
|
||||
// }
|
||||
// );
|
||||
// We build a new descriptor set layout to store our images
|
||||
inputDescriptorLayout = graphStorage->logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, bindings);
|
||||
|
||||
// inputSamplers.push_back(newSampler);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// inputSamplers.push_back({});
|
||||
// }
|
||||
//}
|
||||
// we store a sampler if its an input attachment. if it is storage image, no need sampler, store an empty handle.
|
||||
for (uint32_t i = 0; i < bindings.size(); ++i)
|
||||
{
|
||||
if (bindings[i].Type == vk::DescriptorType::eInputAttachment)
|
||||
{
|
||||
auto newSampler = graphStorage->logicalDevice->CreateSampler(SHVkSamplerParams
|
||||
{
|
||||
.minFilter = vk::Filter::eLinear,
|
||||
.magFilter = vk::Filter::eLinear,
|
||||
.addressMode = vk::SamplerAddressMode::eRepeat,
|
||||
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
||||
.minLod = -1000,
|
||||
.maxLod = 1000
|
||||
}
|
||||
);
|
||||
|
||||
inputSamplers.push_back(newSampler);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputSamplers.push_back({});
|
||||
}
|
||||
}
|
||||
|
||||
//// maybe do this in handle resize?
|
||||
//UpdateWriteDescriptors();
|
||||
|
@ -294,39 +284,43 @@ namespace SHADE
|
|||
|
||||
void SHSubpass::UpdateWriteDescriptors(void) noexcept
|
||||
{
|
||||
//auto const& bindings = inputDescriptorLayout->GetBindings();
|
||||
if (inputNames.empty())
|
||||
return;
|
||||
|
||||
//std::vector<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)
|
||||
// {
|
||||
// // get the resource
|
||||
// auto resource = graphStorage->ptrToResources->at(inputNames[binding.BindPoint]);
|
||||
group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
|
||||
|
||||
// // If resource is swapchain image, get the correct image, if not just get 0.
|
||||
// uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
uint32_t i = 0;
|
||||
for (auto& binding : bindings)
|
||||
{
|
||||
// get the resource
|
||||
auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
|
||||
|
||||
// // layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
|
||||
// vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
|
||||
// If resource is swapchain image, get the correct image, if not just get 0.
|
||||
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
|
||||
|
||||
// // Update descriptor sets
|
||||
// auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout);
|
||||
// group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
|
||||
// group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
|
||||
// }
|
||||
// layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
|
||||
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
|
||||
|
||||
// ++i;
|
||||
//}
|
||||
// Update descriptor sets
|
||||
auto args = std::make_tuple(resource->GetImageView(viewIndex), inputSamplers[i], descriptorLayout);
|
||||
group->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, std::span{&args, 1});
|
||||
group->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
//void SHSubpass::InitComputeBarriers(void) noexcept
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace SHADE
|
|||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorPool;
|
||||
class SHRenderGraphStorage;
|
||||
class SHSubpassCompute;
|
||||
class SHVkShaderModule;
|
||||
class SHVkSampler;
|
||||
|
||||
|
@ -64,9 +63,6 @@ namespace SHADE
|
|||
|
||||
std::vector<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
|
||||
////! swapchain image. If the resource we want to transition is not a swapchain image,
|
||||
|
@ -96,7 +92,9 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
// Preparation functions
|
||||
void AddColorOutput(std::string resourceToReference) noexcept;
|
||||
void AddGeneralColorOutput(std::string resourceToReference) noexcept;
|
||||
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
|
||||
void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
|
||||
void AddInput(std::string resourceToReference) noexcept;
|
||||
void AddGeneralInput (std::string resourceToReference) noexcept;
|
||||
void AddExteriorDrawCalls(std::function<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 HandleResize (void) noexcept;
|
||||
|
||||
Handle<SHSubpassCompute> AddSubpassCompute(Handle<SHVkShaderModule> computeShaderModule/*, std::initializer_list<std::string> resources*/) noexcept;
|
||||
|
||||
void Init(ResourceManager& resourceManager) noexcept;
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
@ -55,6 +55,21 @@ namespace SHADE
|
|||
return 0;
|
||||
}
|
||||
|
||||
vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept
|
||||
{
|
||||
switch (pipelineType)
|
||||
{
|
||||
case SH_PIPELINE_TYPE::GRAPHICS:
|
||||
return vk::PipelineBindPoint::eGraphics;
|
||||
case SH_PIPELINE_TYPE::COMPUTE:
|
||||
return vk::PipelineBindPoint::eCompute;
|
||||
case SH_PIPELINE_TYPE::RAY_TRACING:
|
||||
return vk::PipelineBindPoint::eRayTracingKHR;
|
||||
default:
|
||||
return vk::PipelineBindPoint::eGraphics;
|
||||
}
|
||||
}
|
||||
|
||||
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
|
||||
{
|
||||
if (bufferHandle)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "SHVulkanIncludes.h"
|
||||
|
||||
#include "Resource/Handle.h"
|
||||
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -24,6 +25,7 @@ namespace SHADE
|
|||
static bool IsDepthStencilAttachment (vk::Format format) noexcept;
|
||||
static bool IsBlendCompatible (vk::Format format) noexcept;
|
||||
static uint32_t GetBytesPerPixelFromFormat (vk::Format format) noexcept;
|
||||
static vk::PipelineBindPoint GetPipelineBindPointFromType (SH_PIPELINE_TYPE pipelineType) noexcept;
|
||||
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
|
|
|
@ -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.
|
@ -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.
Loading…
Reference in New Issue