From dc6289e8cf8c6a2b6e815d49bc8f69d6bd9e40b4 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Sun, 25 Sep 2022 23:25:51 +0800 Subject: [PATCH] WIP --- SHADE_Application/src/Scenes/SBTestScene.cpp | 4 +- .../Graphics/Commands/SHVkCommandBuffer.cpp | 234 +++++++++--------- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 3 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 6 +- .../Graphics/RenderGraph/SHRenderGraph.cpp | 36 ++- .../src/Graphics/RenderGraph/SHRenderGraph.h | 2 + 6 files changed, 161 insertions(+), 124 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index c91fee9c..fc2f9731 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -40,8 +40,8 @@ namespace Sandbox // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; - constexpr int NUM_ROWS = 200; - constexpr int NUM_COLS = 100; + constexpr int NUM_ROWS = 1; + constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; for (int z = 0; z < NUM_ROWS; ++z) diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 83095371..eb65598c 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -16,7 +16,7 @@ namespace SHADE { /***************************************************************************/ /*! - + \brief Frees the command buffer. @@ -30,13 +30,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief - Only the command buffer is allocated using - VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting + Only the command buffer is allocated using + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit, is resetting individually permitted. Otherwise, throw exception. IMPORTANT NOTE: the command buffer cannot be in the pending state!!! - + */ /***************************************************************************/ void SHVkCommandBuffer::Reset(void) @@ -67,10 +67,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Begins the command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRecording(void) noexcept @@ -108,10 +108,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief End the recording of a command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRecording(void) noexcept @@ -121,21 +121,21 @@ namespace SHADE SHLOG_ERROR("Command Buffer not in recording state, cannot end recording. "); return; } - + vkCommandBuffer.end(); cmdBufferState = SH_CMD_BUFFER_STATE::EXECUTABLE; } /***************************************************************************/ /*! - + \brief - Begins a renderpass in the command buffer. 2 important things to note - here, the command buffer used MUST be a primary command buffer and + Begins a renderpass in the command buffer. 2 important things to note + here, the command buffer used MUST be a primary command buffer and command buffer MUST be in a recording state. - + \param renderpassHdl - Renderpass for obvious reasons. + Renderpass for obvious reasons. \param framebufferHdl Framebuffer required in the begin info. @@ -145,7 +145,7 @@ namespace SHADE \param extent Extent of the render area in the framebuffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::BeginRenderpass(Handle const& renderpassHdl, Handle const& framebufferHdl, vk::Offset2D offset, vk::Extent2D extent) noexcept @@ -170,7 +170,7 @@ namespace SHADE vk::RenderPassBeginInfo renderPassInfo{}; renderPassInfo.renderPass = renderpassHdl->GetVkRenderpass(); renderPassInfo.framebuffer = framebufferHdl->GetVkFramebuffer(); - + // If the extent passed in is 0, use the framebuffer dimensions instead. if (extent.width == 0 && extent.height == 0) renderPassInfo.renderArea.extent = framebufferExtent; @@ -192,16 +192,16 @@ namespace SHADE } // Begin the render pass - vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); + vkCommandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline); } /***************************************************************************/ /*! - + \brief Ends a renderpass. - + */ /***************************************************************************/ void SHVkCommandBuffer::EndRenderpass(void) noexcept @@ -216,14 +216,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Sets the viewport dynamically for the command buffer. #NoteToSelf: Dynamic state will not affect pipelines that don't use dynamic state so there isn't a need to do any checks. Also, setting dynamic state like this only needs to happen ONCE per command buffer UNLESS a different viewport is to be used for different drawing commands. - + \param vpWidth viewport width @@ -254,7 +254,7 @@ namespace SHADE \param vpMaxDepth viewport maximum depth value - + */ /***************************************************************************/ void SHVkCommandBuffer::SetViewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept @@ -283,13 +283,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Binds a pipeline object to the command buffer. - + \param pipelineHdl The pipeline to bind. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindPipeline(Handle const& pipelineHdl) noexcept @@ -307,7 +307,7 @@ namespace SHADE /*! \brief - Binds a buffer to the vertex buffer binding point specified in + Binds a buffer to the vertex buffer binding point specified in bindingPoint. \param bindingPoint @@ -321,29 +321,32 @@ namespace SHADE */ /***************************************************************************/ - void SHVkCommandBuffer::BindVertexBuffer (uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept + void SHVkCommandBuffer::BindVertexBuffer(uint32_t bindingPoint, Handle const& buffer, vk::DeviceSize offset) noexcept { if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { - auto bufferHandle = buffer->GetVkBuffer(); - vkCommandBuffer.bindVertexBuffers (bindingPoint, 1, &bufferHandle, &offset); + if (buffer) + { + auto bufferHandle = buffer->GetVkBuffer(); + vkCommandBuffer.bindVertexBuffers(bindingPoint, 1, &bufferHandle, &offset); + } } } /***************************************************************************/ /*! - + \brief Binds an index buffer to the pipeline. - + \param buffer The buffer to bind. \param startingIndex - The starting index in the index buffer. For example, 0 would mean - starting at the beginning. 5 would mean starting at byte offset + The starting index in the index buffer. For example, 0 would mean + starting at the beginning. 5 would mean starting at byte offset size(uint32_t) * 5. - + */ /***************************************************************************/ void SHVkCommandBuffer::BindIndexBuffer(Handle const& buffer, uint32_t startingIndex) const noexcept @@ -351,33 +354,33 @@ namespace SHADE if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) { auto bufferHandle = buffer->GetVkBuffer(); - vkCommandBuffer.bindIndexBuffer (bufferHandle, sizeof (uint32_t) * startingIndex, vk::IndexType::eUint32); + vkCommandBuffer.bindIndexBuffer(bufferHandle, sizeof(uint32_t) * startingIndex, vk::IndexType::eUint32); } } void SHVkCommandBuffer::BindDescriptorSet(Handle descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span dynamicOffsets) { - vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); + vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); } /***************************************************************************/ /*! - + \brief Calls vkCmdDraw. - + \param vertexCount How many vertices to draw \param instanceCount Number of instances to draw - + \param firstVertex First vertex in the buffer of vertices to start from \param firstInstance First instance to start from. - + */ /***************************************************************************/ void SHVkCommandBuffer::DrawArrays(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept @@ -387,30 +390,30 @@ namespace SHADE SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); return; } - vkCommandBuffer.draw (vertexCount, instanceCount, firstVertex, firstInstance); + vkCommandBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance); } /***************************************************************************/ /*! - + \brief Issues a non-instanced indexed draw call. - + \param indexCount Number of indices to draw. \param firstIndex Starting index. if the array was 0, 2, 5, 4, and we indicated this to be - 1. The draw call would start from index 2. + 1. The draw call would start from index 2. \param vertexOffset - Starting vertex offset. This would indicate that vertex pulling should + Starting vertex offset. This would indicate that vertex pulling should start from a certain vertex. So a vertex offset of 3 (for example) would mean an index of 0 would mean the 3rd vertex. - + */ /***************************************************************************/ - void SHVkCommandBuffer::DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept + void SHVkCommandBuffer::DrawIndexed(uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept { if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING) { @@ -422,7 +425,7 @@ namespace SHADE vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0); } - + /***************************************************************************/ /*! @@ -445,35 +448,36 @@ namespace SHADE return; } - vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); + if (indirectDrawData) + vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand)); } void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector& copyInfo) { - vkCommandBuffer.copyBufferToImage - ( - src, dst, vk::ImageLayout::eTransferDstOptimal, - static_cast(copyInfo.size()), copyInfo.data() - ); + vkCommandBuffer.copyBufferToImage + ( + src, dst, vk::ImageLayout::eTransferDstOptimal, + static_cast(copyInfo.size()), copyInfo.data() + ); } void SHVkCommandBuffer::PipelineBarrier( - vk::PipelineStageFlags srcStage, - vk::PipelineStageFlags dstStage, - vk::DependencyFlags deps, - std::vector const& memoryBarriers, - std::vector const& bufferMemoryBarriers, - std::vector const& imageMemoryBarriers - ) const noexcept + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept { - vkCommandBuffer.pipelineBarrier ( - srcStage, - dstStage, - deps, - memoryBarriers, - bufferMemoryBarriers, - imageMemoryBarriers - ); + vkCommandBuffer.pipelineBarrier( + srcStage, + dstStage, + deps, + memoryBarriers, + bufferMemoryBarriers, + imageMemoryBarriers + ); } bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept @@ -498,10 +502,10 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Calls vkCmdPushConstants and submits data stored in command buffer. - + */ /***************************************************************************/ void SHVkCommandBuffer::SubmitPushConstants(void) const noexcept @@ -514,13 +518,13 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Simply returns the command buffer handle. - - \return + + \return The command buffer handle. - + */ /***************************************************************************/ vk::CommandBuffer const& SHVkCommandBuffer::GetVkCommandBuffer(void) const noexcept @@ -530,11 +534,11 @@ namespace SHADE /***************************************************************************/ /*! - + \brief - See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html + See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkGetRenderAreaGranularity.html or look up vkGetRenderAreaGranularity. - + \param renderpassHdl Renderpass to get info from. @@ -544,9 +548,9 @@ namespace SHADE \param renderArea For the comparison. Again, look it up on the webpage. - \return + \return If optimal, true. otherwise false. - + */ /***************************************************************************/ bool SHVkCommandBuffer::IsRenderAreaOptimal(Handle const& renderpassHdl, vk::Extent2D const& framebufferExtent, vk::Rect2D const& renderArea) const noexcept @@ -558,14 +562,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Setter for the state of the command buffer. - + \param state - - \return - + + \return + */ /***************************************************************************/ void SHVkCommandBuffer::SetState(SH_CMD_BUFFER_STATE state) noexcept @@ -575,12 +579,12 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Returns the state of the command buffer. - - \return - + + \return + */ /***************************************************************************/ SH_CMD_BUFFER_STATE SHVkCommandBuffer::GetState(void) const noexcept @@ -590,14 +594,14 @@ namespace SHADE /***************************************************************************/ /*! - + \brief Creates a command buffer. Cmd buffer can be primary or secondary. If secondary, flags will automatically have renderpass continue bit. Command pool used to create this command buffer will determine whether or not - this buffer will be allocated with + this buffer will be allocated with VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT using the reset mode. - + \param logicalDevice Need a logical device to create a buffer. @@ -606,7 +610,7 @@ namespace SHADE \param type Type of the command buffer; primary or secondary. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(Handle const& commandPool, SH_CMD_BUFFER_TYPE type) noexcept @@ -616,7 +620,7 @@ namespace SHADE , parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED } , usageFlags{} , commandBufferCount{ 0 } - , parentPool{commandPool} + , parentPool{ commandPool } , pushConstantData{} { @@ -657,54 +661,54 @@ namespace SHADE commandBufferType = type; commandBufferCount = allocateInfo.commandBufferCount; - if (parentPool->GetIsTransient ()) + if (parentPool->GetIsTransient()) usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY) usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue; - + // Reset all the push constant data to 0 - memset (pushConstantData, 0, PUSH_CONSTANT_SIZE); + memset(pushConstantData, 0, PUSH_CONSTANT_SIZE); } /***************************************************************************/ /*! - + \brief Move ctor. Invalidates Vulkan handles. - + \param rhs the other command buffer. - + */ /***************************************************************************/ SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept - : vkCommandBuffer {std::move (rhs.vkCommandBuffer)} - , cmdBufferState {rhs.cmdBufferState} - , commandBufferType {rhs.commandBufferType} - , parentPoolResetMode {rhs.parentPoolResetMode} - , usageFlags {rhs.usageFlags} - , commandBufferCount {rhs.commandBufferCount} - , parentPool {rhs.parentPool} - , boundPipelineLayoutHdl{rhs.boundPipelineLayoutHdl } + : vkCommandBuffer{ std::move(rhs.vkCommandBuffer) } + , cmdBufferState{ rhs.cmdBufferState } + , commandBufferType{ rhs.commandBufferType } + , parentPoolResetMode{ rhs.parentPoolResetMode } + , usageFlags{ rhs.usageFlags } + , commandBufferCount{ rhs.commandBufferCount } + , parentPool{ rhs.parentPool } + , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl } { - memcpy (pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); + memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); rhs.vkCommandBuffer = VK_NULL_HANDLE; } /***************************************************************************/ /*! - + \brief Move assignment operator. Invalidates Vulkan handles. - + \param rhs The other Vulkan Handle. - - \return + + \return a reference itself. - + */ /***************************************************************************/ SHVkCommandBuffer& SHVkCommandBuffer::operator=(SHVkCommandBuffer&& rhs) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 7b2ebd49..f73c5306 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -203,7 +203,8 @@ namespace SHADE } // Transfer to GPU - transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); + if (transformDataBuffer[frameIndex]) + transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); } void SHBatch::Build(Handle _device, uint32_t frameIndex) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index b909aeff..bb2391e3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -150,9 +150,9 @@ namespace SHADE //compositeSubpass->AddInput("Position"); // TODO: Use macro to add this node when SH_EDITOR is enabled - //auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); - //auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); - //imguiSubpass->AddColorOutput("Present"); + auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); + auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); + imguiSubpass->AddColorOutput("Present"); worldRenderGraph->Generate(); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 6070361f..7ef5c0b9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -348,7 +348,7 @@ namespace SHADE void SHSubpass::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept { - // Ensure updated transforms and materials are provided + // Ensure correct transforms are provided superBatch->UpdateBuffers(frameIndex); // Draw all the batches @@ -524,6 +524,7 @@ namespace SHADE , configured{ rhs.configured } , executed{ rhs.executed } , ptrToResources{ rhs.ptrToResources } + , pipelineLibrary{ std::move(rhs.pipelineLibrary) } { rhs.renderpass = {}; } @@ -544,6 +545,7 @@ namespace SHADE resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); subpassIndexing = std::move(rhs.subpassIndexing); ptrToResources = std::move(rhs.ptrToResources); + pipelineLibrary = std::move(rhs.pipelineLibrary); rhs.renderpass = {}; @@ -625,7 +627,7 @@ namespace SHADE } void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) -{ + { batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); } @@ -993,6 +995,34 @@ namespace SHADE } + SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept + : logicalDeviceHdl{ rhs.logicalDeviceHdl } + , swapchainHdl{ rhs.swapchainHdl } + , nodeIndexing{ std::move(rhs.nodeIndexing) } + , nodes{ std::move(rhs.nodes) } + , graphResources{ std::move(rhs.graphResources) } + , resourceManager{ std::move(rhs.resourceManager) } + , globalData{ rhs.globalData } + { + + } + + SHRenderGraph& SHRenderGraph::operator=(SHRenderGraph&& rhs) noexcept + { + if (&rhs == this) + return *this; + + logicalDeviceHdl = rhs.logicalDeviceHdl; + swapchainHdl = rhs.swapchainHdl; + nodeIndexing = std::move(rhs.nodeIndexing); + nodes = std::move(rhs.nodes); + graphResources = std::move(rhs.graphResources); + resourceManager = std::move(rhs.resourceManager); + globalData = rhs.globalData; + + return *this; + } + /***************************************************************************/ /*! @@ -1084,7 +1114,7 @@ namespace SHADE } void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) -{ + { for (auto& node : nodes) { node->FinaliseBatch(frameIndex); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index b8c00417..d5421bdc 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -279,6 +279,8 @@ namespace SHADE /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ SHRenderGraph (void) noexcept; + SHRenderGraph(SHRenderGraph&& rhs) noexcept; + SHRenderGraph& operator=(SHRenderGraph&& rhs) noexcept; /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */