diff --git a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp index e8d6d7bc..5ba016c2 100644 --- a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp +++ b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp @@ -26,87 +26,51 @@ RenderPass::RenderPass(const std::string& name) : { } -void RenderPass::ClearAttachments(PassRenderContext& ctx) +void RenderPass::Execute(PassRenderContext& ctx, PassAttachments& inputs) { - // Resize - for(auto& attachment : Attachments) - { - if (attachment.Image->GetSize() == ctx.resolution) - { - continue; - } - - auto newAttachment = std::make_shared(attachment.Format, ctx.resolution); - attachment.Image = newAttachment; - - // Register to resource manager - auto& gpuResources = GPUResources::Get(); - gpuResources.AddTexture(newAttachment); - - newAttachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); - //VulkanUtil::TransitionImage(ctx.commandBuffer, newAttachment->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); - - // TODO: Queue deletion of old textures - } - - if (DepthAttachment.Image && DepthAttachment.Image->GetSize() != ctx.resolution) - { - Ref newDepthAttachment = std::make_shared(DepthAttachment.Format, ctx.resolution, ImageUsage::Depth); - DepthAttachment.Image = newDepthAttachment; - - auto& gpuResources = GPUResources::Get(); - gpuResources.AddTexture(newDepthAttachment); - - newDepthAttachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); - //VulkanUtil::TransitionImage(ctx.commandBuffer, newDepthAttachment->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, true); - } + ClearAttachments(ctx, inputs); + TransitionAttachments(ctx, inputs); + Render(ctx, inputs); + UntransitionAttachments(ctx, inputs); +} +void RenderPass::ClearAttachments(PassRenderContext& ctx, PassAttachments& inputs) +{ // Clear all color attachments VkClearColorValue clearValue = { { 0.0f, 0.0f, 0.0f, 1.0f } }; VkImageSubresourceRange clearRange = VulkanInit::ImageSubResourceRange(VK_IMAGE_ASPECT_COLOR_BIT); - for (auto& attachment : Attachments) + for (auto& attachment : inputs) { - vkCmdClearColorImage(ctx.commandBuffer,attachment.Image->GetImage(), VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); + if (attachment->GetUsage() != ImageUsage::Depth) + { + vkCmdClearColorImage(ctx.commandBuffer, attachment->GetImage(), VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); + } } - - // Clear depth? } -void RenderPass::TransitionAttachments(PassRenderContext& ctx) +void RenderPass::TransitionAttachments(PassRenderContext& ctx, PassAttachments& inputs) { // Transition all color attachments - for (auto& attachment : Attachments) + for (auto& attachment : inputs) { - //VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - attachment.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - - // Transition depth attachment - if (DepthAttachment.Image) - { - //VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); - //DepthAttachment.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + if (attachment->GetUsage() != ImageUsage::Depth) + { + attachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + } } } -void RenderPass::UntransitionAttachments(PassRenderContext& ctx) +void RenderPass::UntransitionAttachments(PassRenderContext& ctx, PassAttachments& inputs) { - for (auto& attachment : Attachments) + for (auto& attachment : inputs) { // Transform from color attachment to transfer src for next pass - //VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - attachment.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - //VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - attachment.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); - } - - if (DepthAttachment.Image) - { - //VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + attachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + attachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); } } -void RenderPass::Render(PassRenderContext& ctx) +void RenderPass::Render(PassRenderContext& ctx, PassAttachments& inputs) { ctx.renderPass = this; @@ -117,27 +81,27 @@ void RenderPass::Render(PassRenderContext& ctx) // Begin rendering and bind pipeline std::vector renderAttachmentInfos; - renderAttachmentInfos.reserve(Attachments.size()); - - for (auto& attachment : Attachments) - { - VkRenderingAttachmentInfo attachmentInfo = VulkanInit::AttachmentInfo(attachment.Image->GetImageView(), nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - renderAttachmentInfos.push_back(attachmentInfo); - } - VkRenderingAttachmentInfo depthAttachmentInfo = {}; - if (DepthAttachment.Image) + renderAttachmentInfos.reserve(Attachments.size()); + bool hasDepthAttachment = false; + for (auto& attachment : inputs) { - depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + if (attachment->GetUsage() != ImageUsage::Depth) + { + VkRenderingAttachmentInfo attachmentInfo = VulkanInit::AttachmentInfo(attachment->GetImageView(), nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + renderAttachmentInfos.push_back(attachmentInfo); + } + else + { + depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(attachment->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + hasDepthAttachment = true; + } } - VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !DepthAttachment.Image ? nullptr : &depthAttachmentInfo); + VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !hasDepthAttachment ? nullptr : &depthAttachmentInfo); renderInfo.colorAttachmentCount = std::size(renderAttachmentInfos); renderInfo.pColorAttachments = renderAttachmentInfos.data(); - - - // Begin render! vkCmdBeginRendering(ctx.commandBuffer, &renderInfo); { vkCmdBindPipeline(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Pipeline); @@ -165,9 +129,6 @@ void RenderPass::Render(PassRenderContext& ctx) } } vkCmdEndRendering(ctx.commandBuffer); - // End rendering - - if (PostRender) { @@ -380,7 +341,7 @@ bool RenderPipeline::Build() Built = true; } -void RenderPipeline::Execute(PassRenderContext& ctx) +void RenderPipeline::Execute(PassRenderContext& ctx, PipelineAttachments& inputs) { if (!Built) { @@ -388,92 +349,18 @@ void RenderPipeline::Execute(PassRenderContext& ctx) return; } - std::vector transitionedInputs; + int passIndex = 0; for (auto& pass : RenderPasses) { for (auto& input : pass.GetInputAttachments()) { - input.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + //input.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - // //VkImageMemoryBarrier barrier{}; - // //barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - // - // //// Handle old and new layouts based on attachment type - // //barrier.oldLayout = input.Format != ImageFormat::D32F ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - // //barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // - // //input.Image->SetLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - // - // //// Access masks for color or depth-stencil attachments - // //if (input.Format != ImageFormat::D32F) { - // // barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - // // barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // //} - // //else { - // // barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - // // barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - // - // // // Include stencil aspect if applicable - // // //if (input.HasStencilComponent()) { - // // // barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - // // //} - // //} - // - // //// Destination access mask is always for shaders reading - // //barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - // - // //// No queue family ownership transfer in this case - // //barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - // //barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - // - // //// Set the image and subresource range - // //barrier.image = input.Image->GetImage(); - // //barrier.subresourceRange.baseMipLevel = 0; - // //barrier.subresourceRange.levelCount = 1; - // //barrier.subresourceRange.baseArrayLayer = 0; - // //barrier.subresourceRange.layerCount = 1; - // - // //// Choose appropriate source pipeline stage for color or depth-stencil - // //VkPipelineStageFlags srcStage = (input.Format != ImageFormat::D32F) - // // ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - // // : (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - // - // //// Insert the pipeline barrier - // //vkCmdPipelineBarrier( - // // ctx.commandBuffer, - // // srcStage, // Source stage - // // VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // Destination stage - // // 0, - // // 0, nullptr, - // // 0, nullptr, - // // 1, &barrier - // //); - // - // transitionedInputs.push_back(input); - //} - pass.ClearAttachments(ctx); - pass.TransitionAttachments(ctx); - pass.Render(ctx); - pass.UntransitionAttachments(ctx); - - // Sync the attachments + auto& passInputs = inputs[passIndex]; + pass.Render(ctx, inputs[passIndex]); + passIndex++; } - - - for (auto& transitionedOutputs : transitionedInputs) - { - if (transitionedOutputs.Format == ImageFormat::D32F) - { - //VulkanUtil::TransitionImage(ctx.commandBuffer, transitionedOutputs.Image->GetImage(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); - } - else - { - //VulkanUtil::TransitionImage(ctx.commandBuffer, transitionedOutputs.Image->GetImage(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - //transitionedOutputs.Image->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); - } - } - } diff --git a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h index 4f1e38ae..c412cd38 100644 --- a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h +++ b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h @@ -43,6 +43,9 @@ namespace Nuake bool DepthTest = true; }; + using PassAttachments = std::vector>; + + class RenderPass { private: @@ -62,9 +65,6 @@ namespace Nuake std::function PreRender; std::function RenderCb; std::function PostRender; - - // Vulkan structs - public: VkPipeline Pipeline; VkPipelineLayout PipelineLayout; @@ -73,10 +73,13 @@ namespace Nuake RenderPass(const std::string& name); ~RenderPass() = default; - void ClearAttachments(PassRenderContext& ctx); - void TransitionAttachments(PassRenderContext& ctx); - void UntransitionAttachments(PassRenderContext& ctx); - void Render(PassRenderContext& ctx); + void Render(PassRenderContext& ctx, PassAttachments& inputs); + + private: + void Execute(PassRenderContext& ctx, PassAttachments& inputs); + void ClearAttachments(PassRenderContext& ctx, PassAttachments& inputs); + void TransitionAttachments(PassRenderContext& ctx, PassAttachments& inputs); + void UntransitionAttachments(PassRenderContext& ctx, PassAttachments& inputs); public: void SetDepthTest(bool enabled) { HasDepthTest = enabled; } @@ -111,12 +114,13 @@ namespace Nuake }; + using PipelineAttachments = std::vector; + class RenderPipeline { private: bool Built; std::vector RenderPasses; - TextureAttachment FinalOutput; public: RenderPipeline(); ~RenderPipeline() = default; @@ -126,7 +130,6 @@ namespace Nuake RenderPass& GetRenderPass(const std::string& name); bool Build(); - - void Execute(PassRenderContext& ctx); + void Execute(PassRenderContext& ctx, PipelineAttachments& inputs); }; } \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp new file mode 100644 index 00000000..ad99d782 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp @@ -0,0 +1,46 @@ +#include "SceneRenderPipeline.h" +#include "VkResources.h" + +using namespace Nuake; + +SceneRenderPipeline::SceneRenderPipeline(UUID camera) : + CurrentCameraID(camera) +{ + +} + +void SceneRenderPipeline::Render(PassRenderContext& ctx) +{ + // Resize textures + ResizeImage(GBufferAlbedo, ctx.resolution); + ResizeImage(GBufferDepth, ctx.resolution); + ResizeImage(GBufferNormal, ctx.resolution); + ResizeImage(GBufferMaterial, ctx.resolution); + ResizeImage(ShadingOutput, ctx.resolution); + + PipelineAttachments pipelineInputs + { + { GBufferMaterial, GBufferDepth, GBufferNormal, GBufferMaterial }, // GBuffer + { ShadingOutput } // Shading + }; + + GBufferPipeline.Execute(ctx, pipelineInputs); +} + +Ref SceneRenderPipeline::ResizeImage(Ref image, const Vector2& size) +{ + if (image->GetSize() == size) + { + return image; + } + + Ref newAttachment = std::make_shared(image->GetFormat(), size); + + // Register to resource manager + GPUResources& gpuResources = GPUResources::Get(); + gpuResources.AddTexture(newAttachment); + + // We might need to do this? + // newAttachment->TransitionLayout(ctx.commandBuffer, VK_IMAGE_LAYOUT_GENERAL); + return newAttachment; +} diff --git a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h new file mode 100644 index 00000000..0c83d11c --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h @@ -0,0 +1,57 @@ +#pragma once +#include "src/Core/Core.h" +#include "src/Resource/UUID.h" + +#include "src/Rendering/Vulkan/Pipeline/RenderPipeline.h" + +namespace Nuake +{ + class ShadowRenderPipeline + { + private: + UUID CurrentLightID; + Ref DepthTexture; + + static RenderPipeline ShadowPipeline; + + public: + ShadowRenderPipeline() = default; + ~ShadowRenderPipeline() = default; + + void Render(); + + Ref GetOutput() { return DepthTexture; } + }; + + // This class handles all the rendering of the scene + class SceneRenderPipeline + { + private: + UUID CurrentCameraID; + + // Attachments GBuffer + Ref GBufferAlbedo; + Ref GBufferDepth; + Ref GBufferNormal; + Ref GBufferMaterial; + + // Attachments Shading + Ref ShadingOutput; + + // Holds all the texture attachments + static RenderPipeline GBufferPipeline; + + + public: + SceneRenderPipeline(UUID camera); + + SceneRenderPipeline() = default; + ~SceneRenderPipeline() = default; + + void Render(PassRenderContext& ctx); + Ref GetOutput() { return ShadingOutput; } + + private: + Ref ResizeImage(Ref image, const Vector2& size); + }; +} diff --git a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h index bbb109c5..d1b4d703 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h +++ b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h @@ -68,7 +68,7 @@ namespace Nuake ImageFormat GetFormat() const { return Format; } VkImageLayout GetLayout() const { return Layout; } void SetLayout(VkImageLayout layout) { Layout = layout; } - + ImageUsage GetUsage() const { return Usage; } bool IsLayoutTransitionValid(VkImageLayout oldLayout, VkImageLayout newLayout) { switch (oldLayout) { case VK_IMAGE_LAYOUT_UNDEFINED: diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp index dd1f37ce..3bd05c2b 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp @@ -164,7 +164,6 @@ void VkSceneRenderer::BeginScene(RenderContext inContext) passCtx.commandBuffer = inContext.CommandBuffer; passCtx.resolution = Context.Size; - auto view = scene->m_Registry.view(); for (auto e : view) { @@ -175,12 +174,12 @@ void VkSceneRenderer::BeginScene(RenderContext inContext) continue; } - passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID); - ShadowPipeline.Execute(passCtx); + //passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID); + //ShadowPipeline.Execute(passCtx); light.LightMapID = ShadowPipeline.GetRenderPass("Shadow").GetDepthAttachment().Image->GetID(); - //passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID); + //passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(light.m_LightViews[0].CameraID); for (int i = 0; i < CSM_AMOUNT; i++) { //ShadowPipeline.Execute(passCtx); @@ -188,8 +187,8 @@ void VkSceneRenderer::BeginScene(RenderContext inContext) } - passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(Context.CameraID); - GBufferPipeline.Execute(passCtx); + //passCtx.cameraID = GPUResources::Get().GetBindlessCameraID(Context.CameraID); + //GBufferPipeline.Execute(passCtx); } ModelPushConstant modelPushConstant{}; ShadingPushConstant shadingPushConstant; @@ -210,8 +209,6 @@ void VkSceneRenderer::EndScene() VulkanUtil::CopyImageToImage(cmd, selectedOutput.Image->GetImage(), vk.GetDrawImage()->GetImage(), selectedOutput.Image->GetSize(), vk.DrawImage->GetSize()); vk.DrawImage->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL); selectedOutput.Image->TransitionLayout(cmd, VK_IMAGE_LAYOUT_GENERAL); - - } void VkSceneRenderer::CreateBuffers() diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h index 19ef85fc..599ee122 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h @@ -86,6 +86,13 @@ namespace Nuake std::array Data; }; + + + struct CameraSceneRenderer + { + + }; + class VkSceneRenderer { private: