framegraph 同步优化
This commit is contained in:
parent
2a48964aae
commit
7c3198d557
@ -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);
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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{};
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user