Merge pull request #110 from SHADE-DP/SP3-1-Rendering

Added customization for compute shader post processing after renderpass end 
Added customization for compute shader post processing after renderpass end
Added Input attachment descriptor set support (incomplete, still need to bind and handle resizing)
Command buffers now take in a pipeline type to specify bind point. They also now store bind point specific data such as pipeline layout
More descriptor type support
Fixed a bug in batches where the frame index was not correct
Fixed a bug in pipeline layout where the descriptor set layout order was wrong
Render Graph now has 1 extra function at the start of generate where it checks render graph nodes for node computes. If they exist, add another subpass to transition all images involved.
Kirsch node compute for testing is in Graphics System.
Added function in SHVkUtil to convert pipeline type to pipeline bind point
This commit is contained in:
XiaoQiDigipen 2022-10-23 16:57:15 +08:00 committed by GitHub
commit bf2baee144
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 1221 additions and 361 deletions

View File

@ -0,0 +1,54 @@
[Window][MainStatusBar]
Pos=0,1060
Size=1920,20
Collapsed=0
[Window][SHEditorMenuBar]
Pos=0,48
Size=1920,1012
Collapsed=0
[Window][Hierarchy Panel]
Pos=0,142
Size=387,918
Collapsed=0
DockId=0x00000004,0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Inspector]
Pos=1649,48
Size=271,1012
Collapsed=0
DockId=0x00000006,0
[Window][Profiler]
Pos=0,48
Size=387,92
Collapsed=0
DockId=0x00000003,0
[Window][Viewport]
Pos=648,48
Size=2519,1319
Collapsed=0
DockId=0x00000002,0
[Window][ Viewport]
Pos=389,48
Size=1258,1012
Collapsed=0
DockId=0x00000002,0
[Docking][Data]
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,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=1258,1036 CentralNode=1 Selected=0xB41284E7
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252

View File

@ -93,6 +93,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>(); SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::EditorCameraUpdate>();
SHSystemManager::RegisterRoutine<SHCameraSystem, SHCameraSystem::CameraSystemUpdate>();
#ifdef SHEDITOR #ifdef SHEDITOR
SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>(); SHSystemManager::RegisterRoutine<SHEditor, SHEditor::EditorRoutine>();

View File

@ -14,6 +14,7 @@
#include "Physics/Components/SHColliderComponent.h" #include "Physics/Components/SHColliderComponent.h"
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
using namespace SHADE; using namespace SHADE;
@ -155,6 +156,10 @@ namespace Sandbox
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f }); transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f }); transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase"); scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
SHComponentManager::AddComponent<SHCameraComponent>(0);
SHComponentManager::RemoveComponent <SHRigidBodyComponent>(0);
SHComponentManager::RemoveComponent <SHColliderComponent>(0);
} }
void SBTestScene::Update(float dt) void SBTestScene::Update(float dt)

View File

@ -69,7 +69,7 @@ namespace SHADE
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A)) if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
{ {
std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl; //std::cout << "Camera movement: "<<right.x<<", " << right.y << std::endl;
camera.position -= right * dt * camera.movementSpeed; camera.position -= right * dt * camera.movementSpeed;
camera.dirtyView = true; camera.dirtyView = true;
} }
@ -110,7 +110,7 @@ namespace SHADE
camera.dirtyView = true; camera.dirtyView = true;
} }
std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl; //std::cout << "Camera position: " << camera.position.x << " " << camera.position.y << std::endl;
system->UpdateCameraComponent(system->editorCamera); system->UpdateCameraComponent(system->editorCamera);
} }
@ -140,10 +140,11 @@ namespace SHADE
{ {
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID()); auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera.GetEID());
SHVec3 rotation = transform->GetWorldRotation(); SHVec3 rotation = transform->GetWorldRotation();
camera.pitch = rotation.x; camera.pitch = SHMath::RadiansToDegrees(rotation.x);
camera.yaw = rotation.y; camera.yaw = SHMath::RadiansToDegrees(rotation.y);
camera.roll = rotation.z; camera.roll = SHMath::RadiansToDegrees(rotation.z);
camera.position = transform->GetWorldPosition(); camera.position = transform->GetWorldPosition();
camera.dirtyView = true;
} }

View File

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

View File

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

View File

@ -25,7 +25,8 @@ namespace SHADE
} }
SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept
: device{ rhs.device } : ISelfHandle (rhs)
, device{ rhs.device }
, pool{ rhs.pool } , pool{ rhs.pool }
{ {
rhs.pool = VK_NULL_HANDLE; rhs.pool = VK_NULL_HANDLE;

View File

@ -91,7 +91,7 @@ namespace SHADE
// new write for the binding // new write for the binding
updater.writeInfos.emplace_back(); updater.writeInfos.emplace_back();
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); updater.writeHashMap.try_emplace(writeHash, static_cast<uint32_t>(updater.writeInfos.size()) - 1u);
auto& writeInfo = updater.writeInfos.back(); auto& writeInfo = updater.writeInfos.back();
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
@ -102,10 +102,10 @@ namespace SHADE
//case vk::DescriptorType::eSampler: //case vk::DescriptorType::eSampler:
//case vk::DescriptorType::eSampledImage: //case vk::DescriptorType::eSampledImage:
case vk::DescriptorType::eCombinedImageSampler: case vk::DescriptorType::eCombinedImageSampler:
case vk::DescriptorType::eStorageImage:
case vk::DescriptorType::eInputAttachment:
writeInfo.descImageInfos.resize(descriptorCount); writeInfo.descImageInfos.resize(descriptorCount);
break; break;
//case vk::DescriptorType::eStorageImage:
// break;
case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer:
case vk::DescriptorType::eUniformBuffer: case vk::DescriptorType::eUniformBuffer:
@ -165,6 +165,7 @@ namespace SHADE
if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size())
{ {
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
return;
} }
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)

View File

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

View File

@ -233,6 +233,8 @@ namespace SHADE
, vmaAllocator{rhs.vmaAllocator} , vmaAllocator{rhs.vmaAllocator}
, nonDedicatedBestIndex {0} , nonDedicatedBestIndex {0}
, parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl} , parentPhysicalDeviceHdl {rhs.parentPhysicalDeviceHdl}
, uboBufferMemoryAlignment{ 0 }
, ssboBufferMemoryAlignment{ 0 }
{ {
rhs.vkLogicalDevice = VK_NULL_HANDLE; rhs.vkLogicalDevice = VK_NULL_HANDLE;
} }
@ -261,6 +263,8 @@ namespace SHADE
vmaAllocator = rhs.vmaAllocator; vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0; nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl; parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
uboBufferMemoryAlignment = rhs.uboBufferMemoryAlignment;
ssboBufferMemoryAlignment = rhs.ssboBufferMemoryAlignment;
rhs.vkLogicalDevice = VK_NULL_HANDLE; rhs.vkLogicalDevice = VK_NULL_HANDLE;
@ -529,6 +533,11 @@ namespace SHADE
} }
Handle<SHVkPipeline> SHVkLogicalDevice::CreateComputePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl);
}
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params); return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);

View File

@ -175,12 +175,17 @@ namespace SHADE
std::string const& shaderName std::string const& shaderName
) noexcept; ) noexcept;
Handle<SHVkPipeline> CreateGraphicsPipeline ( Handle<SHVkPipeline> CreateGraphicsPipeline (
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, Handle<SHVkPipelineLayout> const& pipelineLayoutHdl,
SHVkPipelineState const* const state, SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass
) noexcept; ) noexcept;
Handle<SHVkPipeline> CreateComputePipeline (
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl
) noexcept;
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept; Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;

View File

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

View File

@ -20,91 +20,91 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp) SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
: subpass { sp } : subpass{ sp }
{} {}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHSuperBatch::Add(const SHRenderable* renderable) noexcept void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Create one if not found
if (batch == batches.end())
{ {
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); batches.emplace_back(PIPELINE);
batch = batches.end() - 1;
// Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Create one if not found
if (batch == batches.end())
{
batches.emplace_back(PIPELINE);
batch = batches.end() - 1;
}
// Add renderable in
batch->Add(renderable);
} }
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept // Add renderable in
batch->Add(renderable);
}
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a Batch with the same pipeline yet
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Attempt to remove if it exists
if (batch == batches.end())
return;
batch->Remove(renderable);
}
void SHSuperBatch::Clear() noexcept
{
for (auto& batch : batches)
{ {
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline(); batch.Clear();
// Check if we have a Batch with the same pipeline yet
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Attempt to remove if it exists
if (batch == batches.end())
return;
batch->Remove(renderable);
} }
batches.clear();
}
void SHSuperBatch::Clear() noexcept void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{
for (auto& batch : batches)
{ {
for (auto& batch : batches) batch.UpdateMaterialBuffer(frameIndex, descPool);
{ batch.UpdateTransformBuffer(frameIndex);
batch.Clear(); batch.UpdateEIDBuffer(frameIndex);
}
batches.clear();
} }
}
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{ {
for (auto& batch : batches) batch.Build(device, descPool, frameIndex);
{
batch.UpdateMaterialBuffer(frameIndex, descPool);
batch.UpdateTransformBuffer(frameIndex);
batch.UpdateEIDBuffer(frameIndex);
}
} }
}
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{ {
// Build all batches batch.Draw(cmdBuffer, frameIndex);
for (auto& batch : batches)
{
batch.Build(device, descPool, frameIndex);
}
}
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Draw(cmdBuffer, frameIndex);
}
} }
}
} }

View File

@ -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, "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("KirschCs.glsl");
cubeVS->Reflect();
cubeFS->Reflect();
greyscale->Reflect();
} }
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -130,6 +147,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto windowDims = window->GetWindowSize(); auto windowDims = window->GetWindowSize();
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
// Set Up Cameras // Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>(); screenCamera = resourceManager.Create<SHCamera>();
@ -154,21 +172,21 @@ namespace SHADE
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init(device, swapchain);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene"}, {}); // no predecessors auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors
//First subpass to write to G-Buffer //First subpass to write to G-Buffer
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Scene"); gBufferWriteSubpass->AddColorOutput("Scene Pre-Process");
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);
// We do this to just transition our scene layout to shader read auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl");
auto sceneLayoutTransitionSubpass = node->AddSubpass("Scene Layout Transition"); node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"});
sceneLayoutTransitionSubpass->AddInput("Scene");
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -177,20 +195,13 @@ 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);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// 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
@ -323,21 +334,7 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
{
worldRenderer->SetViewProjectionMatrix(SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
}
else
{
// main camera
}
#else
// main camera
#endif
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -360,7 +357,7 @@ namespace SHADE
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight()); uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h); currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout()); currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS);
// Bind all the buffers required for meshes // Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA) for (auto& [buffer, bindingPoint] : MESH_DATA)
@ -380,14 +377,29 @@ namespace SHADE
currentCmdBuffer->BindDescriptorSet currentCmdBuffer->BindDescriptorSet
( (
textureDescSet, textureDescSet,
vk::PipelineBindPoint::eGraphics, SH_PIPELINE_TYPE::GRAPHICS,
0, 0,
texDynamicOffset texDynamicOffset
); );
} }
// bind camera data // bind camera data
//renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#ifdef SHEDITOR
if (renderers[renIndex] == worldRenderer)
{
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
}
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
#endif
// Draw first // Draw first
renderers[renIndex]->Draw(frameIndex, descPool); renderers[renIndex]->Draw(frameIndex, descPool);
@ -726,8 +738,8 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR #ifdef SHEDITOR
cameraSystem->GetEditorCamera()->SetWidth(resizeWidth); cameraSystem->GetEditorCamera()->SetWidth(static_cast<float>(resizeWidth));
cameraSystem->GetEditorCamera()->SetHeight(resizeHeight); cameraSystem->GetEditorCamera()->SetHeight(static_cast<float>(resizeHeight));
#else #else
#endif #endif

View File

@ -68,7 +68,7 @@ namespace SHADE
{ {
std::vector combinedImageSampler std::vector combinedImageSampler
{ {
std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal), std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral),
}; };
// Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change // Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Camera/SHCameraDirector.h"
namespace SHADE namespace SHADE
{ {
@ -65,6 +66,11 @@ namespace SHADE
camera = _camera; camera = _camera;
} }
void SHRenderer::SetCameraDirector(Handle<SHCameraDirector> director) noexcept
{
cameraDirector = director;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -75,17 +81,24 @@ namespace SHADE
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{ {
if (camera) if (camera && cameraDirector)
{ {
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix(); UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
} }
} }
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
{
SetViewProjectionMatrix(exteriorMatrix);
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{ {
} }

View File

@ -40,6 +40,7 @@ namespace SHADE
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkBuffer; class SHVkBuffer;
class SHCameraDirector;
struct SHShaderCameraData struct SHShaderCameraData
{ {
@ -71,12 +72,14 @@ namespace SHADE
/* Camera Registration */ /* Camera Registration */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void SetCamera(Handle<SHCamera> _camera); void SetCamera(Handle<SHCamera> _camera);
void SetCameraDirector (Handle<SHCameraDirector> director) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept;
void UpdateCameraDataToBuffer (void) noexcept; void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept; void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
@ -99,6 +102,8 @@ namespace SHADE
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet; Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
Handle<SHVkBuffer> cameraBuffer; Handle<SHVkBuffer> cameraBuffer;
Handle<SHCameraDirector> cameraDirector;
// we really only need 1 copy even though we need %swapchainImages copies for // we really only need 1 copy even though we need %swapchainImages copies for
// GPU. // GPU.
SHShaderCameraData cpuCameraData; SHShaderCameraData cpuCameraData;

View File

@ -8,7 +8,7 @@
namespace SHADE namespace SHADE
{ {
Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
{ {
SHPipelineLayoutParams params SHPipelineLayoutParams params
{ {
@ -52,7 +52,7 @@ namespace SHADE
newPipeline->ConstructPipeline(); newPipeline->ConstructPipeline();
// Emplace the new pipeline // Emplace the new pipeline
pipelines.emplace (vsFsPair, newPipeline); graphicsPipelines.emplace (vsFsPair, newPipeline);
return newPipeline; return newPipeline;
} }
@ -62,19 +62,19 @@ namespace SHADE
logicalDevice = device; logicalDevice = device;
} }
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept Handle<SHVkPipeline> SHPipelineLibrary::GetGraphicsPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{ {
// return the pipeline requested for // return the pipeline requested for
if (pipelines.contains(vsFsPair)) if (graphicsPipelines.contains(vsFsPair))
return pipelines.at(vsFsPair); return graphicsPipelines.at(vsFsPair);
else else
return {}; return {};
} }
bool SHPipelineLibrary::CheckDrawPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept bool SHPipelineLibrary::CheckGraphicsPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{ {
// Returns if a pipeline exists or not // Returns if a pipeline exists or not
return pipelines.contains(vsFsPair); return graphicsPipelines.contains(vsFsPair);
} }
} }

View File

@ -23,19 +23,19 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDevice; Handle<SHVkLogicalDevice> logicalDevice;
//! a map of pipelines that are hashed using a pair of shader module handles //! a map of pipelines that are hashed using a pair of shader module handles
std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> pipelines; std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> graphicsPipelines;
public: public:
void Init (Handle<SHVkLogicalDevice> device) noexcept; void Init (Handle<SHVkLogicalDevice> device) noexcept;
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader // Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
Handle<SHVkPipeline> CreateDrawPipeline ( Handle<SHVkPipeline> CreateGraphicsPipelines (
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
Handle<SHVkRenderpass> renderpass, Handle<SHVkRenderpass> renderpass,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass
) noexcept; ) noexcept;
Handle<SHVkPipeline> GetDrawPipline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
bool CheckDrawPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
}; };
} }

View File

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

View File

@ -4,6 +4,7 @@
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Debugging/SHVulkanDebugUtil.h" #include "Graphics/Debugging/SHVulkanDebugUtil.h"
#include "Graphics/RenderGraph/SHRenderGraph.h" #include "Graphics/RenderGraph/SHRenderGraph.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -171,6 +172,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;
}
} }
@ -245,7 +269,7 @@ namespace SHADE
, logicalDeviceHdl{ rhs.logicalDeviceHdl } , logicalDeviceHdl{ rhs.logicalDeviceHdl }
, pipelineLayout { rhs.pipelineLayout } , pipelineLayout { rhs.pipelineLayout }
{ {
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
} }
/***************************************************************************/ /***************************************************************************/
@ -285,7 +309,8 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
SHVkPipeline::~SHVkPipeline(void) noexcept SHVkPipeline::~SHVkPipeline(void) noexcept
{ {
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr); if (vkPipeline)
logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr);
} }
/***************************************************************************/ /***************************************************************************/
@ -313,7 +338,7 @@ namespace SHADE
created = rhs.created; created = rhs.created;
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
vkPipeline = VK_NULL_HANDLE; rhs.vkPipeline = VK_NULL_HANDLE;
return *this; return *this;
} }
@ -399,18 +424,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept vk::PipelineBindPoint SHVkPipeline::GetPipelineBindPoint(void) const noexcept
{ {
switch (pipelineType) return SHVkUtil::GetPipelineBindPointFromType(pipelineType);
{
case SH_PIPELINE_TYPE::GRAPHICS:
return vk::PipelineBindPoint::eGraphics;
case SH_PIPELINE_TYPE::COMPUTE:
return vk::PipelineBindPoint::eCompute;
break;
default:
return vk::PipelineBindPoint::eGraphics;
break;
}
} }
/***************************************************************************/ /***************************************************************************/
@ -450,4 +464,9 @@ namespace SHADE
return pipelineLayout; return pipelineLayout;
} }
SH_PIPELINE_TYPE SHVkPipeline::GetPipelineType(void) const noexcept
{
return pipelineType;
}
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,8 @@
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "SHAttachmentDescInitParams.h" #include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
namespace SHADE namespace SHADE
{ {
@ -52,12 +54,12 @@ namespace SHADE
// If we set to // If we set to
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{ {
w = swapchainHdl->GetSwapchainImage(0)->GetWidth(); w = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetWidth();
h = swapchainHdl->GetSwapchainImage(0)->GetHeight(); h = renderGraphStorage->swapchain->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format; format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
} }
graphResources.try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(logicalDeviceHdl, swapchainHdl, 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));
} }
/***************************************************************************/ /***************************************************************************/
@ -77,36 +79,38 @@ 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;
} }
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;
} }
@ -292,6 +296,9 @@ namespace SHADE
dep.dstAccessMask = dstAccess; dep.dstAccessMask = dstAccess;
dep.srcStageMask = srcStage; dep.srcStageMask = srcStage;
// initialize input descriptors
node->subpasses[i]->CreateInputDescriptors();
} }
} }
} }
@ -343,10 +350,18 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
{ {
logicalDeviceHdl = logicalDevice; resourceManager = std::make_shared<SHResourceHub>();
swapchainHdl = swapchain;
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();
} }
/***************************************************************************/ /***************************************************************************/
@ -361,24 +376,19 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraph::SHRenderGraph(void) noexcept SHRenderGraph::SHRenderGraph(void) noexcept
: logicalDeviceHdl{ } : renderGraphStorage{}
, swapchainHdl{ }
, nodes{} , nodes{}
, graphResources{}
, resourceManager{nullptr} , resourceManager{nullptr}
{ {
resourceManager = std::make_shared<SHResourceHub>();
} }
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
: logicalDeviceHdl{ rhs.logicalDeviceHdl } : renderGraphStorage{ rhs.renderGraphStorage }
, swapchainHdl{ rhs.swapchainHdl }
, nodeIndexing{ std::move(rhs.nodeIndexing) } , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) } , nodes{ std::move(rhs.nodes) }
, graphResources{ std::move(rhs.graphResources) }
, resourceManager{ std::move(rhs.resourceManager) } , resourceManager{ std::move(rhs.resourceManager) }
{ {
} }
SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept
@ -386,11 +396,9 @@ namespace SHADE
if (&rhs == this) if (&rhs == this)
return *this; return *this;
logicalDeviceHdl = rhs.logicalDeviceHdl; renderGraphStorage = rhs.renderGraphStorage;
swapchainHdl = rhs.swapchainHdl;
nodeIndexing = std::move(rhs.nodeIndexing); nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes); nodes = std::move(rhs.nodes);
graphResources = std::move(rhs.graphResources);
resourceManager = std::move(rhs.resourceManager); resourceManager = std::move(rhs.resourceManager);
return *this; return *this;
@ -426,12 +434,12 @@ namespace SHADE
for (auto const& instruction : resourceInstruction) for (auto const& instruction : resourceInstruction)
{ {
// If the resource that the new node is requesting for exists, allow the graph to reference it // If the resource that the new node is requesting for exists, allow the graph to reference it
if (graphResources.contains(instruction.resourceName)) if (renderGraphStorage->graphResources->contains(instruction.resourceName))
{ {
descInitParams.push_back( descInitParams.push_back(
{ {
.resourceHdl = graphResources.at(instruction.resourceName), .resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
.dontClearOnLoad = false, .dontClearOnLoad = instruction.dontClearOnLoad,
} }
); );
} }
@ -456,7 +464,7 @@ namespace SHADE
} }
} }
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, 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]);
} }
@ -476,12 +484,31 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Generate(void) noexcept void SHRenderGraph::Generate(void) noexcept
{ {
CheckForNodeComputes();
ConfigureAttachmentDescriptions(); ConfigureAttachmentDescriptions();
ConfigureSubpasses(); ConfigureSubpasses();
ConfigureRenderpasses(); ConfigureRenderpasses();
ConfigureFramebuffers(); ConfigureFramebuffers();
} }
/***************************************************************************/
/*!
\brief
This function goes through all renderpasses and checks for existence of
node computes. If they exist, adds dummy subpasses to transition resources
into general.
*/
/***************************************************************************/
void SHRenderGraph::CheckForNodeComputes(void) noexcept
{
for (auto& node : nodes)
{
node->AddDummySubpassIfNeeded();
}
}
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
@ -501,7 +528,7 @@ namespace SHADE
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{ {
// resize resources // resize resources
for (auto& [name, resource]: graphResources) for (auto& [name, resource] : *renderGraphStorage->graphResources)
resource->HandleResize(newWidth, newHeight); resource->HandleResize(newWidth, newHeight);
for (auto& node : nodes) for (auto& node : nodes)
@ -521,9 +548,9 @@ namespace SHADE
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
{ {
if (graphResources.contains(resourceName)) if (renderGraphStorage->graphResources->contains(resourceName))
{ {
return graphResources.at(resourceName); return renderGraphStorage->graphResources->at(resourceName);
} }
return {}; return {};
} }

View File

@ -30,7 +30,8 @@ namespace SHADE
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHRenderGraphNode; class SHRenderGraphNode;
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SH_API SHRenderGraph class SH_API SHRenderGraph
{ {
@ -56,10 +57,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! swapchain used for querying image count Handle<SHRenderGraphStorage> renderGraphStorage;
Handle<SHVkSwapchain> swapchainHdl;
//! For indexing render graph node container //! For indexing render graph node container
std::map<std::string, uint32_t> nodeIndexing; std::map<std::string, uint32_t> nodeIndexing;
@ -67,9 +66,6 @@ namespace SHADE
//! Render graph nodes //! Render graph nodes
std::vector<Handle<SHRenderGraphNode>> nodes; std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resources that exist for the entire render graph
std::unordered_map<std::string, Handle<SHRenderGraphResource>> graphResources;
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<SHResourceHub> resourceManager; std::shared_ptr<SHResourceHub> resourceManager;
@ -85,14 +81,15 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept; void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept; void CheckForNodeComputes (void) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool); void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept; void FinaliseBatch (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */

View File

@ -6,6 +6,9 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "SHSubpass.h" #include "SHSubpass.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -21,7 +24,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHRenderGraphNode::CreateRenderpass(void) noexcept void SHRenderGraphNode::CreateRenderpass(void) noexcept
{ {
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps); renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
} }
/***************************************************************************/ /***************************************************************************/
@ -53,7 +56,7 @@ namespace SHADE
} }
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
} }
} }
@ -79,9 +82,18 @@ namespace SHADE
fbHeight = attResources[j]->height; fbHeight = attResources[j]->height;
} }
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
} }
for (auto& subpass : subpasses)
{
subpass->HandleResize();
}
for (auto& nodeCompute : nodeComputes)
{
nodeCompute->HandleResize();
}
} }
/***************************************************************************/ /***************************************************************************/
@ -104,8 +116,8 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, 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
: logicalDeviceHdl{ logicalDevice } : graphStorage{ renderGraphStorage}
, renderpass{} , renderpass{}
, framebuffers{} , framebuffers{}
, prereqNodes{ std::move(predecessors) } , prereqNodes{ std::move(predecessors) }
@ -115,11 +127,10 @@ namespace SHADE
, subpasses{} , subpasses{}
, executed{ false } , executed{ false }
, configured{ false } , configured{ false }
, resourceManager{ rm } , nodeComputes{}
, ptrToResources{ resources }
{ {
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(logicalDeviceHdl); pipelineLibrary.Init(graphStorage->logicalDevice);
// Store all the handles to resources // Store all the handles to resources
attResources.reserve (attDescInitParams.size()); attResources.reserve (attDescInitParams.size());
@ -155,15 +166,14 @@ namespace SHADE
if (!containsSwapchainImage) if (!containsSwapchainImage)
framebuffers.resize(1); framebuffers.resize(1);
else else
framebuffers.resize(swapchain->GetNumImages()); framebuffers.resize(graphStorage->swapchain->GetNumImages());
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be // At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
// deferred to when renderpasses are also created. // deferred to when renderpasses are also created.
} }
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
: resourceManager{ std::move (rhs.resourceManager) } : graphStorage{ rhs.graphStorage}
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
, renderpass{ rhs.renderpass } , renderpass{ rhs.renderpass }
, framebuffers{ std::move(rhs.framebuffers) } , framebuffers{ std::move(rhs.framebuffers) }
, prereqNodes{ std::move(rhs.prereqNodes) } , prereqNodes{ std::move(rhs.prereqNodes) }
@ -174,11 +184,11 @@ 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) }
, spDeps{ std::move(rhs.spDeps) } , spDeps{ std::move(rhs.spDeps) }
, nodeComputes{ std::move(rhs.nodeComputes) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -189,8 +199,7 @@ namespace SHADE
if (&rhs == this) if (&rhs == this)
return *this; return *this;
resourceManager = std::move(rhs.resourceManager); graphStorage = rhs.graphStorage;
logicalDeviceHdl = rhs.logicalDeviceHdl;
renderpass = rhs.renderpass; renderpass = rhs.renderpass;
framebuffers = std::move(rhs.framebuffers); framebuffers = std::move(rhs.framebuffers);
prereqNodes = std::move(rhs.prereqNodes); prereqNodes = std::move(rhs.prereqNodes);
@ -199,11 +208,11 @@ 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);
spDeps = std::move(rhs.spDeps); spDeps = std::move(rhs.spDeps);
nodeComputes = std::move(rhs.nodeComputes);
rhs.renderpass = {}; rhs.renderpass = {};
@ -235,10 +244,10 @@ namespace SHADE
} }
// Add subpass to container and create mapping for it // Add subpass to container and create mapping for it
subpasses.emplace_back(resourceManager->Create<SHSubpass>(GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*resourceManager); subpass->Init(*graphStorage->resourceManager);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -246,21 +255,84 @@ namespace SHADE
return subpass; return subpass;
} }
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
{
// Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
nodeComputeResources.reserve(resources.size());
for (auto& resourceName : resources)
{
auto resource = graphStorage->graphResources->at(resourceName);
nodeComputeResources.push_back(resource);
}
// Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources));
nodeComputes.push_back(nodeCompute);
return nodeCompute;
}
/***************************************************************************/
/*!
\brief
This function checks all node computes and adds a subpass to transition
all needed resources to general.
*/
/***************************************************************************/
void SHRenderGraphNode::AddDummySubpassIfNeeded(void) noexcept
{
if (!nodeComputes.empty())
{
// we save the resource names involved
std::unordered_set<std::string> resourcesInvolved;
for (auto& compute : nodeComputes)
{
for (auto& resource : compute->resources)
{
resourcesInvolved.emplace(resource->GetName());
}
}
// insert them all for a subpass to transition them. This subpass is the last subpass
auto dummySubpass = AddSubpass("dummy");
for (auto& resource : resourcesInvolved)
{
dummySubpass->AddGeneralInput(resource);
if (SHVkUtil::IsDepthStencilAttachment(graphStorage->graphResources->at(resource)->GetResourceFormat()))
dummySubpass->AddGeneralDepthOutput(resource);
else
dummySubpass->AddGeneralColorOutput(resource);
}
}
}
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{ {
frameIndex = (framebuffers.size() > 1) ? frameIndex : 0; uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
for (uint32_t i = 0; i < subpasses.size(); ++i) for (uint32_t i = 0; i < subpasses.size(); ++i)
{ {
subpasses[i]->Execute(commandBuffer, descPool, frameIndex); subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
// Go to next subpass if not last subpass // Go to next subpass if not last subpass
if (i != subpasses.size() - 1) if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
commandBuffer->NextSubpass(); commandBuffer->NextSubpass();
} }
commandBuffer->EndRenderpass(); commandBuffer->EndRenderpass();
// Execute all subpass computes
for (auto& sbCompute : nodeComputes)
{
sbCompute->Execute(commandBuffer, frameIndex);
}
} }
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
@ -273,10 +345,10 @@ namespace SHADE
} }
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair); Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair);
if (!pipeline) if (!pipeline)
{ {
pipeline = pipelineLibrary.CreateDrawPipeline pipeline = pipelineLibrary.CreateGraphicsPipelines
( (
vsFsPair, vsFsPair,
renderpass, renderpass,
@ -289,7 +361,7 @@ namespace SHADE
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
{ {
batcher.FinaliseBatches(logicalDeviceHdl, descPool, frameIndex); batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -19,6 +19,9 @@ namespace SHADE
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkRenderpass; class SHVkRenderpass;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHGraphicsGlobalData;
class SHRenderGraphStorage;
class SHRenderGraphNodeCompute;
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode> class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
{ {
@ -26,10 +29,9 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
std::shared_ptr<SHResourceHub> resourceManager;
//! For Vulkan object creation //! For Vulkan object creation
Handle<SHVkLogicalDevice> logicalDeviceHdl; //Handle<SHVkLogicalDevice> logicalDeviceHdl;
Handle<SHRenderGraphStorage> graphStorage;
//! Each node will have a renderpass and each renderpass will have its own subpasses. //! Each node will have a renderpass and each renderpass will have its own subpasses.
//! These subpasses will execute sequentially. //! These subpasses will execute sequentially.
@ -63,12 +65,13 @@ 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;
//! Sometimes we want the subpass to do something to the images instead
//! of drawing objects on the image (i.e. compute).
std::vector<Handle<SHRenderGraphNodeCompute>> nodeComputes;
//! Whether or not the node has finished execution //! Whether or not the node has finished execution
bool executed; bool executed;
@ -77,6 +80,7 @@ namespace SHADE
SHBatcher batcher; SHBatcher batcher;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -88,7 +92,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphNode(std::shared_ptr<SHResourceHub> rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, 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;
@ -96,6 +100,9 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept;
void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept; Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;

View File

@ -0,0 +1,109 @@
#include "SHpch.h"
#include "SHRenderGraphNodeCompute.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "SHRenderGraphStorage.h"
#include "SHRenderGraphResource.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
namespace SHADE
{
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale/* = 1.0f*/) noexcept
: computePipeline{}
, pipelineLayout{}
, resources{}
, groupSizeX{0}
, groupSizeY{0}
, numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
{
SHPipelineLayoutParams pipelineLayoutParams
{
.shaderModules = {computeShaderModule},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
};
// Create pipeline layout from parameters
pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams);
// Create the compute pipeline
computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout);
// and construct it
computePipeline->ConstructPipeline();
// save the resources
resources = std::move (subpassComputeResources);
//Get the descriptor set layouts required to allocate. We only want the ones for allocate because
//global descriptors are already bound in the main system.
auto const& layouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsAllocate();
//Variable counts for the descriptor sets (all should be 1).
std::vector<uint32_t> variableCounts{ static_cast<uint32_t>(layouts.size()) };
std::fill(variableCounts.begin(), variableCounts.end(), 0);
// Allocate descriptor sets to hold the images for reading (STORAGE_IMAGE)
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{
descSetGroups[i] = graphStorage->descriptorPool->Allocate(layouts, variableCounts);
}
HandleResize();
}
void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// bind the compute pipeline
cmdBuffer->BindPipeline(computePipeline);
// bind descriptor sets
cmdBuffer->BindDescriptorSet(descSetGroups[frameIndex], SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, {});
// dispatch compute
cmdBuffer->ComputeDispatch(groupSizeX, groupSizeY, 1);
// TODO: barrier
}
void SHRenderGraphNodeCompute::HandleResize(void) noexcept
{
// Get the layout for the render graph resource. We can index it this way because the container returned is a container of layouts that includes the global ones
auto pipelineDescSetLayouts = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
// everything below here needs resizing
for (uint32_t frameIndex = 0; frameIndex < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++frameIndex)
{
uint32_t i = 0;
// loop through bindings and write descriptor sets
for (auto& binding : pipelineDescSetLayouts->GetBindings())
{
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
descSetGroups[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
descSetGroups[frameIndex]->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint);
++i;
}
}
// Get the group size from the max width and height
uint32_t maxWidth = 0, maxHeight = 0;
for (auto& resource : resources)
{
maxWidth = std::max(resource->GetWidth(), maxWidth);
maxHeight = std::max(resource->GetHeight(), maxHeight);
}
groupSizeX = maxWidth / workGroupSizeX;
groupSizeY = maxHeight / workGroupSizeY;
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include "Resource/SHHandle.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include <initializer_list>
#include <string>
#include <unordered_set>
namespace SHADE
{
class SHVkPipeline;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHVkLogicalDevice;
class SHVkPipelineLayout;
class SHRenderGraphStorage;
class SHRenderGraphResource;
class SHVkShaderModule;
class SHVkCommandBuffer;
class SHRenderGraphNodeCompute
{
private:
static constexpr uint32_t workGroupSizeX = 16;
static constexpr uint32_t workGroupSizeY = 16;
//! To run the dispatch command
Handle<SHVkPipeline> computePipeline;
//! Pipeline layout for the pipeline creation
Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set group to hold the images for reading (STORAGE_IMAGE)
std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS> descSetGroups;
//! vector of resources needed by the subpass compute
std::vector<Handle<SHRenderGraphResource>> resources;
//! X dimension work group size. Should scale with resource size.
uint32_t groupSizeX;
//! Y dimension work group size
uint32_t groupSizeY;
float numWorkGroupScale;
public:
SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, float inNumWorkGroupScale = 1.0f) noexcept;
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
friend class SHRenderGraph;
friend class SHRenderGraphNode;
};
}

View File

@ -5,6 +5,7 @@
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "SHRenderGraphStorage.h"
namespace SHADE namespace SHADE
{ {
@ -45,9 +46,8 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: logicalDevice {logicalDevice} : graphStorage{renderGraphStorage}
, swapchain{ swapchain }
, resourceTypeFlags{ } , resourceTypeFlags{ }
, resourceFormat{ format } , resourceFormat{ format }
, images{} , images{}
@ -66,7 +66,7 @@ namespace SHADE
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
{ {
.viewType = vk::ImageViewType::e2D, .viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format, .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor, .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
.mipLevelCount = 1, .mipLevelCount = 1,
@ -75,13 +75,13 @@ namespace SHADE
}; };
// We want an image handle for every swapchain image // We want an image handle for every swapchain image
images.resize(swapchain->GetNumImages()); images.resize(graphStorage->swapchain->GetNumImages());
imageViews.resize(swapchain->GetNumImages()); imageViews.resize(graphStorage->swapchain->GetNumImages());
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
{ {
images[i] = swapchain->GetSwapchainImage(i); images[i] = graphStorage->swapchain->GetSwapchainImage(i);
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails); imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails);
} }
} }
else // if swapchain image resource else // if swapchain image resource
@ -117,6 +117,9 @@ namespace SHADE
usage |= vk::ImageUsageFlagBits::eInputAttachment; usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled; usage |= vk::ImageUsageFlagBits::eSampled;
break; break;
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
usage |= vk::ImageUsageFlagBits::eStorage;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT: case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
{ {
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. "); SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
@ -126,7 +129,7 @@ namespace SHADE
} }
// The resource is not a swapchain image, just use the first slot of the vector // The resource is not a swapchain image, just use the first slot of the vector
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags)); images.push_back(graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
// prepare image view details // prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -141,7 +144,7 @@ namespace SHADE
}; };
// just 1 image view created // just 1 image view created
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails)); imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails));
} }
} }
@ -166,7 +169,7 @@ namespace SHADE
, height{ rhs.height } , height{ rhs.height }
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags } , imageAspectFlags{ rhs.imageAspectFlags }
, swapchain {rhs.swapchain} , graphStorage{rhs.graphStorage}
{ {
} }
@ -198,7 +201,7 @@ namespace SHADE
height = rhs.height; height = rhs.height;
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags; imageAspectFlags = rhs.imageAspectFlags;
swapchain = rhs.swapchain; graphStorage = rhs.graphStorage;
return *this; return *this;
} }
@ -247,7 +250,7 @@ namespace SHADE
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
{ {
.viewType = vk::ImageViewType::e2D, .viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format, .format = graphStorage->swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor, .imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0, .baseMipLevel = 0,
.mipLevelCount = 1, .mipLevelCount = 1,
@ -255,9 +258,9 @@ namespace SHADE
.layerCount = 1, .layerCount = 1,
}; };
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) for (uint32_t i = 0; i < graphStorage->swapchain->GetNumImages(); ++i)
{ {
images[i] = swapchain->GetSwapchainImage(i); images[i] = graphStorage->swapchain->GetSwapchainImage(i);
imageViews[i]->ViewNewImage(images[i], viewDetails); imageViews[i]->ViewNewImage(images[i], viewDetails);
} }
} }
@ -308,6 +311,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 +327,19 @@ 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;
}
std::string SHRenderGraphResource::GetName(void) const noexcept
{
return resourceName;
}
} }

View File

@ -15,6 +15,7 @@ namespace SHADE
class SHVkSwapchain; class SHVkSwapchain;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkBuffer; class SHVkBuffer;
class SHRenderGraphStorage;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0; static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
@ -24,11 +25,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// for creation/recreation //! Storage from the render graph
Handle<SHVkLogicalDevice> logicalDevice; Handle<SHRenderGraphStorage> graphStorage;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource //! Name of the resource
std::string resourceName; std::string resourceName;
@ -69,7 +67,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept; SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
@ -84,12 +82,17 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
vk::Format GetResourceFormat (void) const noexcept; vk::Format GetResourceFormat (void) const noexcept;
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;
std::string GetName (void) const noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass;
friend class SHRenderGraphNodeCompute;
}; };
} }

View File

@ -0,0 +1,43 @@
#pragma once
#include "Resource/SHHandle.h"
#include <memory>
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkSwapchain;
class SHGraphicsGlobalData;
class SHVkDescriptorPool;
class SHRenderGraphResource;
class SHRenderGraphStorage
{
//! Logical device for creation of vulkan objects
Handle<SHVkLogicalDevice> logicalDevice;
//! swapchain handle
Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects
std::shared_ptr<SHResourceHub> resourceManager;
//! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool;
//! 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 SHRenderGraphNodeCompute;
};
}

View File

@ -4,6 +4,13 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "SHRenderGraphNode.h" #include "SHRenderGraphNode.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "SHRenderGraphNode.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkSampler.h"
#include "SHRenderGraphResource.h"
namespace SHADE namespace SHADE
{ {
@ -23,15 +30,16 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHSubpass::SHSubpass(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{}
, colorReferences{} , colorReferences{}
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
, graphStorage{ renderGraphStorage }
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
{ {
} }
@ -54,9 +62,14 @@ 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{ rhs.graphStorage }
, inputNames{ std::move(rhs.inputNames) }
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
, inputDescriptorLayout{ rhs.inputDescriptorLayout }
, inputSamplers{ rhs.inputSamplers }
{ {
} }
@ -84,9 +97,13 @@ 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 = rhs.graphStorage;
inputNames = std::move(rhs.inputNames);
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
inputDescriptorLayout = rhs.inputDescriptorLayout;
inputSamplers = rhs.inputSamplers;
return *this; return *this;
} }
@ -105,7 +122,12 @@ 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->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 });
} }
/***************************************************************************/ /***************************************************************************/
@ -142,7 +164,13 @@ namespace SHADE
//Invalid //Invalid
return; return;
} }
depthReferences.push_back({ resourceAttachmentMapping->at(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 });
} }
/***************************************************************************/ /***************************************************************************/
@ -159,7 +187,14 @@ 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->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->graphResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eGeneral });
} }
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
@ -175,6 +210,12 @@ namespace SHADE
{ {
drawCall(commandBuffer); drawCall(commandBuffer);
} }
}
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
@ -188,6 +229,152 @@ namespace SHADE
} }
void SHSubpass::CreateInputDescriptors(void) noexcept
{
if (inputNames.empty())
return;
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,
.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
{
if (inputNames.empty())
return;
auto const& bindings = inputDescriptorLayout->GetBindings();
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);
uint32_t i = 0;
for (auto& binding : bindings)
{
// get the resource
auto resource = graphStorage->graphResources->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,7 +14,11 @@ namespace SHADE
class SHRenderGraphResource; class SHRenderGraphResource;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SHVkShaderModule;
class SHVkSampler;
class SH_API SHSubpass : public ISelfHandle<SHSubpass> class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{ {
@ -22,32 +26,49 @@ namespace SHADE
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
Handle<SHRenderGraphStorage> graphStorage;
//! The index of the subpass in the render graph //! The index of the subpass in the render graph
uint32_t subpassIndex; uint32_t subpassIndex;
//! The parent renderpass that this subpass belongs to //! 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 //! Descriptor set layout to hold attachments
Handle<SHVkDescriptorSetLayout> descriptorSetLayout; Handle<SHVkDescriptorSetLayout> descriptorSetLayout;
//! Color attachments //! Color attachments
std::vector<vk::AttachmentReference> colorReferences; std::vector<vk::AttachmentReference> colorReferences;
//! Depth attachments //! Depth attachments
std::vector<vk::AttachmentReference> depthReferences; std::vector<vk::AttachmentReference> depthReferences;
//! 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;
////! 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.
@ -62,7 +83,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHSubpass(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;
@ -71,14 +92,22 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Preparation functions // Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept; void AddColorOutput(std::string resourceToReference) noexcept;
void AddGeneralColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept; void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
void AddInput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept;
void 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;
void Init(SHResourceHub& resourceManager) noexcept; void Init(SHResourceHub& resourceManager) noexcept;
//void InitComputeBarriers (void) noexcept;
void CreateInputDescriptors (void) noexcept;
void UpdateWriteDescriptors (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
@ -91,5 +120,6 @@ namespace SHADE
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; friend class SHRenderGraph;
friend class SHSubpass;
}; };
} }

View File

@ -1,23 +0,0 @@
#include "SHpch.h"
#include "SHSubpassCompute.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
namespace SHADE
{
SHSubpassCompute::SHSubpassCompute(Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept
: pipeline {inPipeline}
{
// 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();
// 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)
descPool->Allocate(layouts, variableCounts);
}
}

View File

@ -1,25 +0,0 @@
#pragma once
#include <Resource/SHHandle.h>
namespace SHADE
{
class SHVkPipeline;
class SHVkDescriptorSetGroup;
class SHVkDescriptorPool;
class SHSubpassCompute
{
private:
//! To run the dispatch command
Handle<SHVkPipeline> pipeline;
//! Descriptor set group
Handle<SHVkDescriptorSetGroup> descSetGroup;
public:
SHSubpassCompute (Handle<SHVkPipeline> inPipeline, Handle<SHVkDescriptorPool> descPool) noexcept;
};
}

View File

@ -55,6 +55,21 @@ namespace SHADE
return 0; return 0;
} }
vk::PipelineBindPoint SHVkUtil::GetPipelineBindPointFromType(SH_PIPELINE_TYPE pipelineType) noexcept
{
switch (pipelineType)
{
case SH_PIPELINE_TYPE::GRAPHICS:
return vk::PipelineBindPoint::eGraphics;
case SH_PIPELINE_TYPE::COMPUTE:
return vk::PipelineBindPoint::eCompute;
case SH_PIPELINE_TYPE::RAY_TRACING:
return vk::PipelineBindPoint::eRayTracingKHR;
default:
return vk::PipelineBindPoint::eGraphics;
}
}
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{ {
if (bufferHandle) if (bufferHandle)

View File

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

View File

@ -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,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.