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.position -= UP * dt * camera.movementSpeed;
system->editorCamera.dirtyView = true; system->editorCamera.dirtyView = true;
} }
system->UpdateCameraComponent(system->editorCamera); system->UpdateCameraComponent(system->editorCamera);
} }

View File

@ -63,6 +63,14 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t PER_INSTANCE = 3; 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); graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
graphicsTexCmdBuffer = 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 void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -166,6 +183,13 @@ namespace SHADE
gBufferWriteSubpass->AddColorOutput("Entity ID"); gBufferWriteSubpass->AddColorOutput("Entity ID");
gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
auto greyscale = shaderModuleLibrary.GetShaderModule("GreyscaleCs.glsl");
auto greyscaleSubpass = node->AddSubpass("Greyscale Subpass");
greyscaleSubpass->AddGeneralInput("Scene");
greyscaleSubpass->AddSubpassCompute(greyscale);
// We do this to just transition our scene layout to shader read // We do this to just transition our scene layout to shader read
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition");
sceneLayoutTransitionSubpass->AddInput("Scene"); sceneLayoutTransitionSubpass->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 = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); 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 cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept

View File

@ -171,6 +171,29 @@ namespace SHADE
void SHVkPipeline::CreateComputePipeline(void) noexcept 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, DEPTH_STENCIL = 0x10,
INPUT = 0x20 INPUT = 0x20
}; };
} }

View File

@ -10,6 +10,7 @@
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h" #include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpassCompute.h"
namespace SHADE namespace SHADE
{ {
@ -78,36 +79,48 @@ namespace SHADE
for (uint32_t i = 0; auto& node : nodes) for (uint32_t i = 0; auto& node : nodes)
{ {
// key is handle ID, value is pair (first is initial layout, second is final layout). // key is handle ID, value is final layout.
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts; std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
if (node->subpasses.empty()) if (node->subpasses.empty())
{ {
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. "); SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
return; return;
} }
// attempt to get all final layouts for all resources
for (auto& subpass : node->subpasses) for (auto& subpass : node->subpasses)
{ {
for (auto& color : subpass->colorReferences) 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))) 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 else
resourceAttLayouts[color.attachment] = color.layout; resourceAttFinalLayouts[color.attachment] = color.layout;
} }
for (auto& depth : subpass->depthReferences) for (auto& depth : subpass->depthReferences)
resourceAttLayouts[depth.attachment] = depth.layout; resourceAttFinalLayouts[depth.attachment] = depth.layout;
for (auto& input : subpass->inputReferences) 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) for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
{ {
auto& att = node->attachmentDescriptions[j]; auto& att = node->attachmentDescriptions[j];
att.initialLayout = vk::ImageLayout::eUndefined; att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[j]; att.finalLayout = resourceAttFinalLayouts[j];
} }
++i; ++i;
} }
@ -175,7 +188,7 @@ namespace SHADE
// Now we want to loop through all attachments in all subpasses in the node and query // Now we want to loop through all attachments in all subpasses in the node and query
// the resources being used. For each resource we want to query the type and record it // the resources being used. For each resource we want to query the type and record it
// in bit fields (1 bit for each subpass). // in bit fields (1 bit for each subpass).
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0; uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0, descriptorDependencies = 0;
uint32_t i = 0; uint32_t i = 0;
@ -214,6 +227,9 @@ namespace SHADE
if (subpass->inputReferences.size()) if (subpass->inputReferences.size())
inputDependencies |= (1 << i); inputDependencies |= (1 << i);
if (!subpass->subpassComputes.empty())
descriptorDependencies |= (1 << i);
// Input attachments can be any type, so we need to check what type it is // Input attachments can be any type, so we need to check what type it is
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
@ -279,6 +295,12 @@ namespace SHADE
dstAccess |= vk::AccessFlagBits::eInputAttachmentRead; dstAccess |= vk::AccessFlagBits::eInputAttachmentRead;
} }
if (descriptorDependencies & (1 << i))
{
dstStage |= vk::PipelineStageFlagBits::eComputeShader;
dstAccess |= vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eShaderRead;
}
//// If subpass of first renderpass, stage flag should be bottom of pipe //// If subpass of first renderpass, stage flag should be bottom of pipe
//if (&node == &nodes.front() && i == 0) //if (&node == &nodes.front() && i == 0)
// srcStage = vk::PipelineStageFlagBits::eBottomOfPipe; // srcStage = vk::PipelineStageFlagBits::eBottomOfPipe;
@ -293,6 +315,9 @@ namespace SHADE
dep.dstAccessMask = dstAccess; dep.dstAccessMask = dstAccess;
dep.srcStageMask = srcStage; dep.srcStageMask = srcStage;
// initialize the barriers
//node->subpasses[i]->InitComputeBarriers();
} }
} }
} }
@ -353,6 +378,8 @@ namespace SHADE
renderGraphStorage->resourceManager = resourceManager; renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); 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); nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]); return nodes.at(nodeIndexing[nodeName]);
} }

View File

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

View File

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

View File

@ -64,9 +64,6 @@ namespace SHADE
//! For indexing subpasses //! For indexing subpasses
std::map<std::string, uint32_t> subpassIndexing; 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 //! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
SHPipelineLibrary pipelineLibrary; SHPipelineLibrary pipelineLibrary;
@ -89,7 +86,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* 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(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;

View File

@ -308,6 +308,7 @@ namespace SHADE
return resourceFormat; return resourceFormat;
} }
uint32_t SHRenderGraphResource::GetWidth(void) const noexcept uint32_t SHRenderGraphResource::GetWidth(void) const noexcept
{ {
return width; return width;
@ -323,4 +324,14 @@ namespace SHADE
return imageViews [index]; 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

@ -86,8 +86,11 @@ namespace SHADE
uint32_t GetWidth (void) const noexcept; uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept; uint32_t GetHeight (void) const noexcept;
Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept; Handle<SHVkImageView> GetImageView (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
uint8_t GetMipLevels (void) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; 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 //! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool; Handle<SHVkDescriptorPool> descriptorPool;
//! For accessing resources anyone in the graph
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHSubpass; friend class SHSubpass;

View File

@ -8,6 +8,10 @@
#include "SHRenderGraphNode.h" #include "SHRenderGraphNode.h"
#include "SHRenderGraphStorage.h" #include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpassCompute.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 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 } : resourceAttachmentMapping{ mapping }
, ptrToResources{ resources }
, parentNode{ parent } , parentNode{ parent }
, subpassIndex{ index } , subpassIndex{ index }
, superBatch{} , superBatch{}
@ -37,6 +40,8 @@ namespace SHADE
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
, graphStorage{ renderGraphStorage } , graphStorage{ renderGraphStorage }
, subpassComputes{}
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
{ {
} }
@ -59,10 +64,10 @@ namespace SHADE
, depthReferences{ std::move(rhs.depthReferences) } , depthReferences{ std::move(rhs.depthReferences) }
, inputReferences{ std::move(rhs.inputReferences) } , inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping } , resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
, ptrToResources{ rhs.ptrToResources }
, descriptorSetLayout{ rhs.descriptorSetLayout } , descriptorSetLayout{ rhs.descriptorSetLayout }
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) } , exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
, graphStorage{ std::move(rhs.graphStorage) } , graphStorage{ std::move(rhs.graphStorage) }
, subpassComputes{std::move (rhs.subpassComputes)}
{ {
} }
@ -90,10 +95,10 @@ namespace SHADE
depthReferences = std::move(rhs.depthReferences); depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences); inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping; resourceAttachmentMapping = rhs.resourceAttachmentMapping;
ptrToResources = rhs.ptrToResources;
descriptorSetLayout = rhs.descriptorSetLayout; descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = std::move(rhs.graphStorage); graphStorage = std::move(rhs.graphStorage);
subpassComputes = std::move(rhs.subpassComputes);
return *this; return *this;
} }
@ -112,7 +117,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept 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 //Invalid
return; 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 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 void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@ -182,6 +195,17 @@ namespace SHADE
{ {
drawCall(commandBuffer); drawCall(commandBuffer);
} }
// if there are subpass computes, transition all to GENERAL layout first
for (auto& sbCompute : subpassComputes)
{
}
}
void SHSubpass::HandleResize(void) noexcept
{
UpdateWriteDescriptors();
} }
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
@ -189,9 +213,27 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall); 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; 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 SHRenderGraphResource;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHRenderGraphStorage; class SHRenderGraphStorage;
class SHSubpassCompute; class SHSubpassCompute;
class SHVkShaderModule; class SHVkShaderModule;
class SHVkSampler;
class SH_API SHSubpass : public ISelfHandle<SHSubpass> class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{ {
@ -48,15 +50,29 @@ namespace SHADE
//! Input attachments //! 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 //! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping; std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Pointer to resources in the render graph (for getting handle IDs) //! Descriptor set group to hold the images for input
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources; 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 //! Sometimes we want the subpass to do something to the images instead
//! of drawing objects on the image (i.e. compute). //! 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 //! 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. //! 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 */ /* 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(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -82,15 +98,21 @@ namespace SHADE
void AddColorOutput(std::string resourceToReference) noexcept; 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 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 AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
// Runtime functions // Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void 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 Init(ResourceManager& resourceManager) noexcept;
//void InitComputeBarriers (void) noexcept;
void CreateInputDescriptors (void) noexcept;
void UpdateWriteDescriptors (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -102,5 +124,6 @@ namespace SHADE
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass;
}; };
} }

View File

@ -11,25 +11,43 @@
namespace SHADE 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{} : pipeline{}
{ {
SHPipelineLayoutParams pipelineLayoutParams SHPipelineLayoutParams pipelineLayoutParams
{ {
.shaderModules = {computeShaderModule},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts() .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. // Create the compute pipeline
auto const& layouts = pipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate(); 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). // Variable counts for the descriptor sets (all should be 1).
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) }; //std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) };
std::fill(variableCounts.begin(), variableCounts.end(), 0); //std::fill(variableCounts.begin(), variableCounts.end(), 0);
// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE) //// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
descSetGroup = graphStorage->descriptorPool->Allocate(layouts, variableCounts); //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 "Resource/Handle.h"
#include <initializer_list> #include <initializer_list>
#include <string> #include <string>
#include <unordered_set>
namespace SHADE namespace SHADE
{ {
@ -12,6 +13,7 @@ namespace SHADE
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkPipelineLayout; class SHVkPipelineLayout;
class SHRenderGraphStorage; class SHRenderGraphStorage;
class SHRenderGraphResource;
class SHVkShaderModule; class SHVkShaderModule;
class SHSubpassCompute class SHSubpassCompute
@ -20,18 +22,28 @@ namespace SHADE
//! To run the dispatch command //! To run the dispatch command
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
//! Pipeline layout for the pipline creation //! Pipeline layout for the pipeline creation
Handle<SHVkPipeline> pipelineLayout; Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE) ////! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
Handle<SHVkDescriptorSetGroup> descSetGroup; //Handle<SHVkDescriptorSetGroup> descSetGroup;
//! Required resources to be used in the descriptors ////! Required resources to be used in the descriptors
std::vector<std::string> resourcesRequired; //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: 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; return vk::DescriptorType::eStorageBufferDynamic;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
return vk::DescriptorType::eInputAttachment; return vk::DescriptorType::eInputAttachment;
case SpvReflectDescriptorType::SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
return vk::DescriptorType::eStorageImage;
break;
default: default:
return vk::DescriptorType::eCombinedImageSampler; return vk::DescriptorType::eCombinedImageSampler;
break; 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.