This commit is contained in:
Brandon Mak 2022-10-21 20:56:14 +08:00
parent e8073bb67f
commit cc6e2189fa
19 changed files with 437 additions and 75 deletions

View File

@ -62,6 +62,7 @@ namespace SHADE
system->editorCamera.position -= UP * dt * camera.movementSpeed;
system->editorCamera.dirtyView = true;
}
system->UpdateCameraComponent(system->editorCamera);
}

View File

@ -63,6 +63,14 @@ namespace SHADE
*/
/***************************************************************************/
static constexpr uint32_t PER_INSTANCE = 3;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for render graph resources.
*/
/***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
};

View File

@ -115,6 +115,23 @@ namespace SHADE
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
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);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
greyscale->Reflect();
}
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -166,6 +183,13 @@ namespace SHADE
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");
@ -177,20 +201,11 @@ namespace SHADE
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
}
void SHGraphicsSystem::InitMiddleEnd(void) noexcept

View File

@ -171,6 +171,29 @@ namespace SHADE
void SHVkPipeline::CreateComputePipeline(void) noexcept
{
auto shaderModule = pipelineLayout->GetShaderModules()[0];
vk::PipelineShaderStageCreateInfo shaderStageCreateInfo
{
.stage = vk::ShaderStageFlagBits::eCompute,
.module = shaderModule->GetVkShaderModule(),
.pName = shaderModule->GetEntryPoint().c_str(),
};
vk::ComputePipelineCreateInfo cpCreateInfo
{
.flags = {},
.stage = shaderStageCreateInfo,
.layout = pipelineLayout->GetVkPipelineLayout(),
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createComputePipelines({}, 1, &cpCreateInfo, nullptr, &vkPipeline); result != vk::Result::eSuccess)
SHVulkanDebugUtil::ReportVkError(result, "Failed to create Compute Pipeline. ");
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Compute Pipeline. ");
created = true;
}
}

View File

@ -12,4 +12,5 @@ namespace SHADE
DEPTH_STENCIL = 0x10,
INPUT = 0x20
};
}

View File

@ -10,6 +10,7 @@
#include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpassCompute.h"
namespace SHADE
{
@ -78,36 +79,48 @@ namespace SHADE
for (uint32_t i = 0; auto& node : nodes)
{
// key is handle ID, value is pair (first is initial layout, second is final layout).
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts;
// key is handle ID, value is final layout.
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
if (node->subpasses.empty())
{
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
return;
}
// attempt to get all final layouts for all resources
for (auto& subpass : node->subpasses)
{
for (auto& color : subpass->colorReferences)
{
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else
resourceAttLayouts[color.attachment] = color.layout;
resourceAttFinalLayouts[color.attachment] = color.layout;
}
for (auto& depth : subpass->depthReferences)
resourceAttLayouts[depth.attachment] = depth.layout;
resourceAttFinalLayouts[depth.attachment] = depth.layout;
for (auto& input : subpass->inputReferences)
resourceAttLayouts[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)
{
auto& att = node->attachmentDescriptions[j];
att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[j];
att.finalLayout = resourceAttFinalLayouts[j];
}
++i;
}
@ -175,7 +188,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;
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0, descriptorDependencies = 0;
uint32_t i = 0;
@ -214,6 +227,9 @@ 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)
{
@ -279,6 +295,12 @@ 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;
@ -293,6 +315,9 @@ namespace SHADE
dep.dstAccessMask = dstAccess;
dep.srcStageMask = srcStage;
// initialize the barriers
//node->subpasses[i]->InitComputeBarriers();
}
}
}
@ -353,6 +378,8 @@ namespace SHADE
renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
renderGraphStorage->ptrToResources = &graphResources;
}
/***************************************************************************/
@ -459,7 +486,7 @@ namespace SHADE
}
}
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors), &graphResources));
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]);
}

View File

@ -57,10 +57,6 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
//Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! swapchain used for querying image count
//Handle<SHVkSwapchain> swapchainHdl;
Handle<SHRenderGraphStorage> renderGraphStorage;

View File

@ -83,6 +83,11 @@ namespace SHADE
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
}
for (auto& subpass : subpasses)
{
subpass->HandleResize();
}
}
/***************************************************************************/
@ -105,7 +110,7 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept
: graphStorage{ renderGraphStorage}
, renderpass{}
, framebuffers{}
@ -116,7 +121,6 @@ namespace SHADE
, subpasses{}
, executed{ false }
, configured{ false }
, ptrToResources{ resources }
{
// pipeline library initialization
pipelineLibrary.Init(graphStorage->logicalDevice);
@ -173,7 +177,6 @@ namespace SHADE
, subpassIndexing{ std::move(rhs.subpassIndexing) }
, configured{ rhs.configured }
, executed{ rhs.executed }
, ptrToResources{ rhs.ptrToResources }
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
, batcher{ std::move(rhs.batcher) }
, spDescs{ std::move(rhs.spDescs) }
@ -197,7 +200,6 @@ namespace SHADE
subpasses = std::move(rhs.subpasses);
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
subpassIndexing = std::move(rhs.subpassIndexing);
ptrToResources = std::move(rhs.ptrToResources);
pipelineLibrary = std::move(rhs.pipelineLibrary);
batcher = std::move(rhs.batcher);
spDescs = std::move(rhs.spDescs);
@ -233,7 +235,7 @@ namespace SHADE
}
// Add subpass to container and create mapping for it
subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), subpasses.size(), &resourceAttachmentMapping));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*graphStorage->resourceManager);

View File

@ -64,9 +64,6 @@ namespace SHADE
//! For indexing subpasses
std::map<std::string, uint32_t> subpassIndexing;
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
SHPipelineLibrary pipelineLibrary;
@ -89,7 +86,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;

View File

@ -308,6 +308,7 @@ namespace SHADE
return resourceFormat;
}
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
{
return width;
@ -323,4 +324,14 @@ namespace SHADE
return imageViews [index];
}
Handle<SHVkImage> SHRenderGraphResource::GetImage(uint32_t index /*= NON_SWAPCHAIN_RESOURCE_INDEX*/) const noexcept
{
return images[index];
}
uint8_t SHRenderGraphResource::GetMipLevels(void) const noexcept
{
return mipLevels;
}
}

View File

@ -82,12 +82,15 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Format GetResourceFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept;
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
vk::Format GetResourceFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) 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;
uint8_t GetMipLevels (void) const noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;
friend class SHSubpass;
};
}

View File

@ -24,6 +24,9 @@ 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;
friend class SHRenderGraph;
friend class SHRenderGraphNode;
friend class SHSubpass;

View File

@ -8,6 +8,10 @@
#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"
#include "SHRenderGraphResource.h"
namespace SHADE
{
@ -27,9 +31,8 @@ namespace SHADE
*/
/***************************************************************************/
SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept
: resourceAttachmentMapping{ mapping }
, ptrToResources{ resources }
, parentNode{ parent }
, subpassIndex{ index }
, superBatch{}
@ -37,6 +40,8 @@ namespace SHADE
, depthReferences{}
, inputReferences{}
, graphStorage{ renderGraphStorage }
, subpassComputes{}
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
{
}
@ -59,10 +64,10 @@ namespace SHADE
, depthReferences{ std::move(rhs.depthReferences) }
, inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, ptrToResources{ rhs.ptrToResources }
, descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
, graphStorage{ std::move(rhs.graphStorage) }
, subpassComputes{std::move (rhs.subpassComputes)}
{
}
@ -90,10 +95,10 @@ namespace SHADE
depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
ptrToResources = rhs.ptrToResources;
descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = std::move(rhs.graphStorage);
subpassComputes = std::move(rhs.subpassComputes);
return *this;
}
@ -112,7 +117,7 @@ namespace SHADE
/***************************************************************************/
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
{
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
colorReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
}
/***************************************************************************/
@ -149,7 +154,7 @@ namespace SHADE
//Invalid
return;
}
depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
depthReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
}
/***************************************************************************/
@ -166,7 +171,15 @@ namespace SHADE
/***************************************************************************/
void SHSubpass::AddInput(std::string resourceToReference) noexcept
{
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
inputReferences.push_back({ resourceAttachmentMapping->at(graphStorage->ptrToResources->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 });
}
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@ -182,6 +195,17 @@ namespace SHADE
{
drawCall(commandBuffer);
}
// if there are subpass computes, transition all to GENERAL layout first
for (auto& sbCompute : subpassComputes)
{
}
}
void SHSubpass::HandleResize(void) noexcept
{
UpdateWriteDescriptors();
}
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
@ -189,9 +213,27 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall);
}
Handle<SHSubpassCompute> SHSubpass::ActivateSubpassCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources) noexcept
Handle<SHSubpassCompute> SHSubpass::AddSubpassCompute(Handle<SHVkShaderModule> computeShaderModule/*, std::initializer_list<std::string> resources*/) noexcept
{
subpassCompute = graphStorage->resourceManager->Create<SHSubpassCompute>(graphStorage, computeShaderModule, resources);
//// 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;
}
@ -201,6 +243,145 @@ namespace SHADE
}
void SHSubpass::CreateInputDescriptors(void) noexcept
{
//std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
//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 = {},
// };
// bindings.push_back(newBinding);
//}
//// We build a new descriptor set layout to store our images
//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.
//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();
}
void SHSubpass::UpdateWriteDescriptors(void) noexcept
{
//auto const& bindings = inputDescriptorLayout->GetBindings();
//std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(bindings.size()), 0 };
//uint32_t i = 0;
//// For every frame's descriptor set
//for (auto& group : inputImageDescriptors)
//{
// if (group)
// group.Free();
// group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
// for (auto& binding : bindings)
// {
// // 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 viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
// // 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;
// // 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
//{
// std::unordered_set <uint64_t> handleBarriers{};
// // we will have swapchainNumImages vectors of vector of barriers
// subpassComputeBarriers.resize(graphStorage->swapchain->GetNumImages());
// for (auto sbCompute : subpassComputes)
// {
// // for every resource the subpass compute is using
// for (auto resource : sbCompute->resources)
// {
// // Get the resource handle
// uint64_t resourceRaw = resource.GetId().Raw;
// // if the barrier is not registered
// if (!handleBarriers.contains(resourceRaw))
// {
// // If the resource is a swapchain image
// bool isSwapchainImage = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT));
// for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
// {
// // if swapchain image, we want the index of the swapchain image, if not take base image
// uint32_t imageIndex = isSwapchainImage ? i : 0;
// // Prepare image barrier
// vk::ImageMemoryBarrier imageBarrier
// {
// .oldLayout = colorReferences[resourceAttachmentMapping->at(resource.GetId().Raw)].layout,
// .newLayout = vk::ImageLayout::eGeneral,
// .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
// .image = resource->GetImage(imageIndex)->GetVkImage(),
// .subresourceRange =
// {
// .aspectMask = resource->imageAspectFlags,
// .levelCount = resource->GetMipLevels(),
// .baseArrayLayer = 0,
// .layerCount = 1
// }
// };
// // push the barrier
// subpassComputeBarriers[i].push_back(imageBarrier);
// }
// // Image transition registered
// handleBarriers.emplace(resourceRaw);
// }
// }
// }
//}
/***************************************************************************/
/*!

View File

@ -14,10 +14,12 @@ namespace SHADE
class SHRenderGraphResource;
class SHVkCommandBuffer;
class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SHSubpassCompute;
class SHVkShaderModule;
class SHVkSampler;
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{
@ -25,38 +27,52 @@ namespace SHADE
/*---------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*---------------------------------------------------------------------*/
Handle<SHRenderGraphStorage> graphStorage;
Handle<SHRenderGraphStorage> graphStorage;
//! The index of the subpass in the render graph
uint32_t subpassIndex;
uint32_t subpassIndex;
//! The parent renderpass that this subpass belongs to
Handle<SHRenderGraphNode> parentNode;
Handle<SHRenderGraphNode> parentNode;
//!
Handle<SHSuperBatch> superBatch;
Handle<SHSuperBatch> superBatch;
//! Descriptor set layout to hold attachments
Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
//! Color attachments
std::vector<vk::AttachmentReference> colorReferences;
std::vector<vk::AttachmentReference> colorReferences;
//! Depth attachments
std::vector<vk::AttachmentReference> depthReferences;
std::vector<vk::AttachmentReference> depthReferences;
//! Input attachments
std::vector<vk::AttachmentReference> inputReferences;
std::vector<vk::AttachmentReference> inputReferences;
//! This is mainly for when we want to retrieve resources using names.
std::vector<std::string> inputNames;
//! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Descriptor set group to hold the images for input
std::vector<Handle<SHVkDescriptorSetGroup>> inputImageDescriptors;
//! Descriptor set layout for allocating descriptor set for inputs
Handle<SHVkDescriptorSetLayout> inputDescriptorLayout;
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).
Handle<SHSubpassCompute> subpassCompute;
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,
////! we duplicate the barrier anyway, not much memory wasted. ;)
//std::vector<std::vector<vk::ImageMemoryBarrier>> subpassComputeBarriers{};
//! Sometimes there exists entities that we want to render onto a render target
//! but don't want it to come from the batching system. An example would be ImGUI.
@ -71,7 +87,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -82,14 +98,20 @@ namespace SHADE
void AddColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
// Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
void HandleResize (void) noexcept;
Handle<SHSubpassCompute> ActivateSubpassCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources) noexcept;
Handle<SHSubpassCompute> AddSubpassCompute(Handle<SHVkShaderModule> computeShaderModule/*, std::initializer_list<std::string> resources*/) noexcept;
void Init(ResourceManager& resourceManager) noexcept;
//void InitComputeBarriers (void) noexcept;
void CreateInputDescriptors (void) noexcept;
void UpdateWriteDescriptors (void) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
@ -102,5 +124,6 @@ namespace SHADE
friend class SHRenderGraphNode;
friend class SHRenderGraph;
friend class SHSubpass;
};
}

View File

@ -11,25 +11,43 @@
namespace SHADE
{
SHSubpassCompute::SHSubpassCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources) noexcept
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()
};
//pipeline = logicalDevice->CreateComputePipeline()
// Create descriptor set from
pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams);
// Get the descriptor set layouts required to allocate. we will bind a different pipeline layout, one that includes the layout for global.
auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
// 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);
//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);
//// 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

@ -3,6 +3,7 @@
#include "Resource/Handle.h"
#include <initializer_list>
#include <string>
#include <unordered_set>
namespace SHADE
{
@ -12,26 +13,37 @@ namespace SHADE
class SHVkLogicalDevice;
class SHVkPipelineLayout;
class SHRenderGraphStorage;
class SHRenderGraphResource;
class SHVkShaderModule;
class SHSubpassCompute
{
private:
//! To run the dispatch command
Handle<SHVkPipeline> pipeline;
Handle<SHVkPipeline> pipeline;
//! Pipeline layout for the pipline creation
Handle<SHVkPipeline> pipelineLayout;
//! Pipeline layout for the pipeline creation
Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
Handle<SHVkDescriptorSetGroup> descSetGroup;
////! 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;
////! 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::initializer_list<std::string> resources) noexcept;
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

@ -177,6 +177,9 @@ namespace SHADE
return vk::DescriptorType::eStorageBufferDynamic;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return vk::DescriptorType::eInputAttachment;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
return vk::DescriptorType::eStorageImage;
break;
default:
return vk::DescriptorType::eCombinedImageSampler;
break;

View File

@ -0,0 +1,38 @@
/* 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.