framegraph 同步优化

This commit is contained in:
ouczbs 2024-12-14 17:57:33 +08:00
parent 2a48964aae
commit 7c3198d557
12 changed files with 70 additions and 22 deletions

View File

@ -8,6 +8,7 @@ namespace api {
RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept
: graph(*graph) , node(node) {}; : graph(*graph) , node(node) {};
FrameGraph::RenderPassBuilder& Name(pmr::Name name); FrameGraph::RenderPassBuilder& Name(pmr::Name name);
FrameGraph::RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None);
FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state); FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state);
FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state); FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state);
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state); FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state);

View File

@ -80,14 +80,29 @@ namespace api {
} }
void ResolveView(FrameGraph* graph); void ResolveView(FrameGraph* graph);
}; };
enum class RenderPassNodeType : uint16_t {
None,
Scene,
Imgui,
};
enum class RenderPassNodeFlag : uint16_t
{
None = 0,
Input = 0x01,
Output = 0x02,
};
using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>; using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>;
struct RenderPassNode { struct RenderPassNode {
Name name; Name name;
size_t hash; size_t hash;
RenderPassNodeType type;
RenderPassNodeFlag flag;
RenderPassNodeExecuteFn executor; RenderPassNodeExecuteFn executor;
pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() }; pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() };
pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() }; pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() };
void ForeachEdge(RenderPassEdgeIterFn fn); void ForeachEdge(RenderPassEdgeIterFn fn);
bool IsInput() { return any(flag & RenderPassNodeFlag::Input); }
bool IsOutput() { return any(flag & RenderPassNodeFlag::Output); }
FrameGraphEdgePtr GetInput(int i) { return inEdges[i]; }; FrameGraphEdgePtr GetInput(int i) { return inEdges[i]; };
FrameGraphEdgePtr GetOutput(int i) { return outEdges[i]; }; FrameGraphEdgePtr GetOutput(int i) { return outEdges[i]; };
FrameGraphEdgePtr FindInput(Name name) FrameGraphEdgePtr FindInput(Name name)

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "meta/enum.h"
#include "refl/pch.h" #include "refl/pch.h"
#include "tinyimageformat/tinyimageformat_base.h" #include "tinyimageformat/tinyimageformat_base.h"
#include <cstdint> #include <cstdint>

View File

@ -1,12 +1,17 @@
#include "render/graph/frame_graph.h" #include "render/graph/frame_graph.h"
#include "render/pass/render_pass.h" #include "render/pass/render_pass.h"
#include "meta/enum.h"
namespace api { namespace api {
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name) FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
{ {
node->name = name; node->name = name;
return *this; return *this;
} }
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Type(RenderPassNodeType type, RenderPassNodeFlag flag)
{
node->type = type;
node->flag = flag;
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state) FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state)
{ {
FrameGraphEdgePtr edge{}; FrameGraphEdgePtr edge{};

View File

@ -20,6 +20,7 @@ namespace api {
.Import(FrameGraph::NameSurface, surface, ResourceState::COLOR_ATTACHMENT) .Import(FrameGraph::NameSurface, surface, ResourceState::COLOR_ATTACHMENT)
.Edge(); .Edge();
builder.Name("MiniPass") builder.Name("MiniPass")
.Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Input | RenderPassNodeFlag::Output)
.Write(edge, edge.targetState); .Write(edge, edge.targetState);
} }
void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx) void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx)

View File

@ -2,7 +2,6 @@
#include "render/asset/ubo.h" #include "render/asset/ubo.h"
#include "render/renderapi.h" #include "render/renderapi.h"
#include "zlog.h" #include "zlog.h"
#include "meta/enum.h"
#include <shaderc/shaderc.hpp> #include <shaderc/shaderc.hpp>
#include <spirv_cross/spirv_reflect.hpp> #include <spirv_cross/spirv_reflect.hpp>
namespace api namespace api

View File

@ -59,7 +59,7 @@ namespace vkn {
uint8_t subpassMask;// 1 byte uint8_t subpassMask;// 1 byte
uint8_t initialColorLayoutMask;// 1 byte uint8_t initialColorLayoutMask;// 1 byte
uint8_t needsResolveMask; // 1 byte uint8_t needsResolveMask; // 1 byte
operator size_t() { operator size_t() const{
return meta::MurmurHashFn(this); return meta::MurmurHashFn(this);
} }
}; };

View File

@ -18,6 +18,7 @@ namespace vkn {
table<Guid, MeshVAO> MeshTable; table<Guid, MeshVAO> MeshTable;
table<Guid, VulkanPipeline> PipelineTable; table<Guid, VulkanPipeline> PipelineTable;
table<size_t, RenderPassInfo> RenderPassCache; table<size_t, RenderPassInfo> RenderPassCache;
table<Name, RenderPassInfo> RenderPassNameCache;
table<FramebufferKey, VkFramebuffer> FramebufferCache; table<FramebufferKey, VkFramebuffer> FramebufferCache;
public: public:
VulkanAPI(); VulkanAPI();
@ -40,7 +41,8 @@ namespace vkn {
void EndRenderPass(RenderPassNode* node) override; void EndRenderPass(RenderPassNode* node) override;
void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override; void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override;
VkPipeline GetPipeline() { return nullptr; }; VkPipeline GetPipeline() { return nullptr; };
const RenderPassInfo& GetRenderPassInfo(size_t hash, const RenderPassKey& config = {}); RenderPassInfo* GetRenderPassInfo(Name name, size_t hash);
RenderPassInfo* GetRenderPassInfo(size_t& hash, const RenderPassKey& config);
Backend& GetBackend() { Backend& GetBackend() {
return backend; return backend;
} }

View File

@ -7,7 +7,6 @@
#include "vkn/loader/vulkan_glsl_loader.h" #include "vkn/loader/vulkan_glsl_loader.h"
#include "render/asset/mesh.h" #include "render/asset/mesh.h"
#include "event/event_system.h" #include "event/event_system.h"
#include "meta/enum.h"
#include "tinyimageformat/tinyimageformat_apis.h" #include "tinyimageformat/tinyimageformat_apis.h"
#include "zlog.h" #include "zlog.h"
namespace vkn { namespace vkn {
@ -375,6 +374,7 @@ namespace vkn {
} }
void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback)
{ {
RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash);
RenderPassKey config{}; RenderPassKey config{};
FramebufferKey frameKey{.layers = 1}; FramebufferKey frameKey{.layers = 1};
VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 }; VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 };
@ -398,9 +398,10 @@ namespace vkn {
} }
} }
frameKey.attachmentCount = i; frameKey.attachmentCount = i;
node->hash = config; if (!passInfo) {
RenderPassInfo passInfo = GetRenderPassInfo(node->hash, config); passInfo = GetRenderPassInfo(node->hash, config);
frameKey.pass = passInfo.Pass(); }
frameKey.pass = passInfo->Pass();
auto it = FramebufferCache.find(frameKey); auto it = FramebufferCache.find(frameKey);
VkFramebuffer framebuffer = it->second; VkFramebuffer framebuffer = it->second;
if (it == FramebufferCache.end()) { if (it == FramebufferCache.end()) {
@ -430,7 +431,7 @@ namespace vkn {
.pClearValues = clearValues .pClearValues = clearValues
}; };
VulkanContext& ctx = *(VulkanContext*)&context; VulkanContext& ctx = *(VulkanContext*)&context;
CommandBuffer cmd = passInfo.commands[context.frame]; CommandBuffer cmd = passInfo->commands[context.frame];
ctx.command = cmd.Ptr(); ctx.command = cmd.Ptr();
cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
if(callback) callback(node); if(callback) callback(node);
@ -439,41 +440,59 @@ namespace vkn {
void VulkanAPI::EndRenderPass(RenderPassNode* node) void VulkanAPI::EndRenderPass(RenderPassNode* node)
{ {
VulkanContext& ctx = *(VulkanContext*)&context; VulkanContext& ctx = *(VulkanContext*)&context;
RenderPassInfo passInfo = GetRenderPassInfo(node->hash); RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash);
CommandBuffer cmd = passInfo.commands[context.frame]; CommandBuffer cmd = passInfo->commands[context.frame];
vkCmdEndRenderPass(cmd.Ptr()); vkCmdEndRenderPass(cmd.Ptr());
cmd.EndRecord(); cmd.EndRecord();
VkSemaphore waitSemaphores[8]; VkSemaphore waitSemaphores[8];
VkPipelineStageFlags waitDstStageMasks[8]; VkPipelineStageFlags waitDstStageMasks[8];
uint32_t semaphoreCount = 0; uint32_t semaphoreCount = 0;
if (ctx.surfaceSemaphore) { if (node->IsInput()) {
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore; waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore;
ctx.surfaceSemaphore = nullptr; zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore);
} }
for (auto& it : node->inEdges) { for (auto& it : node->inEdges) {
RenderPassInfo inputInfo = GetRenderPassInfo(it->source->hash); RenderPassInfo* inputInfo = GetRenderPassInfo(it->source->name ,it->source->hash);
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
waitSemaphores[semaphoreCount++] = inputInfo.semaphores[context.frame]; waitSemaphores[semaphoreCount++] = inputInfo->semaphores[context.frame];
zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]);
} }
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cmd.Ptr(); submitInfo.pCommandBuffers = &cmd.Ptr();
submitInfo.pSignalSemaphores = &passInfo.semaphores[context.frame]; submitInfo.pSignalSemaphores = &passInfo->semaphores[context.frame];
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitDstStageMasks; submitInfo.pWaitDstStageMask = waitDstStageMasks;
submitInfo.waitSemaphoreCount = semaphoreCount; submitInfo.waitSemaphoreCount = semaphoreCount;
if (!ctx.graphSemaphore) { if (node->IsOutput()) {
ctx.graphSemaphore = passInfo.semaphores[context.frame]; ctx.graphSemaphore = passInfo->semaphores[context.frame];
} }
zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]);
vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr); vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr);
} }
const RenderPassInfo& VulkanAPI::GetRenderPassInfo(size_t hash, const RenderPassKey& config) { RenderPassInfo* VulkanAPI::GetRenderPassInfo(Name name, size_t hash) {
if (hash) {
auto it = RenderPassCache.find(hash);
if (it != RenderPassCache.end()) {
return &it->second;
}
}
if (name) {
auto it = RenderPassNameCache.find(name);
if (it != RenderPassNameCache.end()) {
return &it->second;
}
}
return nullptr;
}
RenderPassInfo* VulkanAPI::GetRenderPassInfo(size_t& hash, const RenderPassKey& config) {
hash = config;
auto it = RenderPassCache.find(hash); auto it = RenderPassCache.find(hash);
if (it != RenderPassCache.end()) { if (it != RenderPassCache.end()) {
return it->second; return &it->second;
} }
// Set up some const aliases for terseness. // Set up some const aliases for terseness.
const VkAttachmentLoadOp kClear = VK_ATTACHMENT_LOAD_OP_CLEAR; const VkAttachmentLoadOp kClear = VK_ATTACHMENT_LOAD_OP_CLEAR;
@ -644,6 +663,6 @@ namespace vkn {
backend.GetDevice().CreateSemaphores(info.semaphores, context.frameCount); backend.GetDevice().CreateSemaphores(info.semaphores, context.frameCount);
Backend::RenderWorker->GetCommandPool().PopList(info.commands, context.frameCount); Backend::RenderWorker->GetCommandPool().PopList(info.commands, context.frameCount);
RenderPassCache.emplace(hash, info); RenderPassCache.emplace(hash, info);
return RenderPassCache[hash]; return &RenderPassCache[hash];
} }
} }

View File

@ -1,6 +1,5 @@
#include <tuple> #include <tuple>
#include "vkn/vulkan_api_help.h" #include "vkn/vulkan_api_help.h"
#include "meta/enum.h"
namespace vkn { namespace vkn {
VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit) VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit)
{ {

View File

@ -1,5 +1,6 @@
#include "vkn/vulkan_context.h" #include "vkn/vulkan_context.h"
#include "vkn/backend.h" #include "vkn/backend.h"
#include "zlog.h"
namespace vkn { namespace vkn {
void VulkanContext::SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) void VulkanContext::SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
{ {
@ -57,6 +58,7 @@ namespace vkn {
}; };
vkBeginCommandBuffer(surfaceCommand, &beginInfo); vkBeginCommandBuffer(surfaceCommand, &beginInfo);
} }
void VulkanContext::EndRecord(VkQueue queue) void VulkanContext::EndRecord(VkQueue queue)
{ {
vkEndCommandBuffer(surfaceCommand); vkEndCommandBuffer(surfaceCommand);
@ -74,6 +76,8 @@ namespace vkn {
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]);
zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]);
vkQueueSubmit(queue, 1, &submitInfo, surfaceFence); vkQueueSubmit(queue, 1, &submitInfo, surfaceFence);
graphSemaphore = nullptr; graphSemaphore = nullptr;
} }

View File

@ -98,9 +98,11 @@ namespace vkn {
vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame); vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame);
vkResetFences(mDevice.Ptr(), 1, &surfaceFence); vkResetFences(mDevice.Ptr(), 1, &surfaceFence);
ctx.presentFrame = ctx.presentFrame % mFrames; ctx.presentFrame = ctx.presentFrame % mFrames;
zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore);
} }
void VulkanSwapchain::Present(VulkanContext& ctx) void VulkanSwapchain::Present(VulkanContext& ctx)
{ {
zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore);
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pWaitSemaphores = &ctx.presentSemaphore; presentInfo.pWaitSemaphores = &ctx.presentSemaphore;