diff --git a/engine/3rdparty/xmake.lua b/engine/3rdparty/xmake.lua index 5edf4ca..5e19495 100644 --- a/engine/3rdparty/xmake.lua +++ b/engine/3rdparty/xmake.lua @@ -1,4 +1,4 @@ -add_requires("spdlog", "lemon", "libsdl", "vulkansdk","shaderc","spirv","spirv-cross") +add_requires("spdlog", "libsdl", "vulkansdk","shaderc","spirv","spirv-cross") add_requires("mimalloc", {configs = {shared = true, debug = true, copy = true}}) add_requires("imgui",{configs = {shared = true, debug = true, copy = true}}) includes("*/xmake.lua") \ No newline at end of file diff --git a/engine/modules/engine/core/include/module/module.inl b/engine/modules/engine/core/include/module/module.inl index 7f2b627..c1f8236 100644 --- a/engine/modules/engine/core/include/module/module.inl +++ b/engine/modules/engine/core/include/module/module.inl @@ -3,7 +3,7 @@ namespace api { template struct ModuleRegistrantImpl; struct IDynamicModule : public IModule { - SharedLibrary mSharedLib; + SharedLibrary mSharedLib{}; }; struct DefaultDynamicModule : public IDynamicModule { DefaultDynamicModule(Name name) : IDynamicModule() {}; diff --git a/engine/modules/engine/render/include/render/graph/frame_graph.h b/engine/modules/engine/render/include/render/graph/frame_graph.h index d309e2c..6d108c6 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph.h @@ -9,11 +9,12 @@ namespace api { class RenderPassBuilder; public: inline static Name NameSurface{ "surface" }; + RenderPassNode* mFirstInputNode{ nullptr }; + RenderPassNode* mLastOutputNode{ nullptr }; TextureDesc mSurface; table mTextureTable; table mTexturePool; table mTextureViewPool; - lemon::ListGraph mGraph; pmr::vector mNodes{FramePool()}; public: template @@ -21,10 +22,12 @@ namespace api { using RenderPassSetupFunction = std::function; FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor); TextureBuilder CreateTextureBuild(); - void InitSurface(const pmr::vector& surfaces); + void InitSurface(span surfaces); void Compile(); void Execute(FRenderView& view); void Clear(); + void CullGraph(); + void FillGraph(); ResourceState Resolve(Name name,TextureDesc& desc, ResourceState state); ResourceState Resolve(Name name, AttachmentDesc& desc, ResourceState state); ResourceState Resolve(Name name, BufferDesc& desc, ResourceState state); diff --git a/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl b/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl index b03dd2f..e6702ff 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl +++ b/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl @@ -20,7 +20,7 @@ namespace api { FrameGraphEdgePtr edge; public: TextureBuilder(FrameGraph* graph)noexcept : graph(*graph) { edge.Make(); }; - FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc, ResourceState state); - FrameGraphEdgePtr Edge() { return edge; } + FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc); + FrameGraphEdgePtr Edge() const { return edge; } }; } \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/graph/type.h b/engine/modules/engine/render/include/render/graph/type.h index 99dc726..7c24552 100644 --- a/engine/modules/engine/render/include/render/graph/type.h +++ b/engine/modules/engine/render/include/render/graph/type.h @@ -1,7 +1,6 @@ #pragma once #include "asset/asset.h" #include "render/type.h" -#include "lemon/list_graph.h" #include namespace api { struct RenderPassNode; @@ -14,7 +13,7 @@ namespace api { RenderContext* operator->() { return parent; } - size_t PassKey(); + size_t PassKey()const; }; struct CopyPassContext {}; @@ -27,12 +26,10 @@ namespace api { class RenderPassNode; struct FrameGraphNodePtr { using NodeType = RenderPassType; - using GraphNodeRef = lemon::ListGraphBase::Node; - GraphNodeRef ref; - NodeType type{ NodeType::Render }; RenderPassNode* node; + NodeType type{ NodeType::Render }; FrameGraphNodePtr() : node(nullptr){}; - FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); + FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); operator bool() const { return node; } @@ -50,13 +47,13 @@ namespace api { T& CastTo() { return std::get(resource); } - bool IsAttachment() { + bool IsAttachment() const { return std::holds_alternative(resource); } - bool IsTexture() { + bool IsTexture() const{ return std::holds_alternative(resource); } - bool IsBuffer() { + bool IsBuffer() const { return std::holds_alternative(resource); } }; @@ -72,6 +69,9 @@ namespace api { resource = new (FramePool()) FrameResource(); return resource; } + RenderPassNode* SourceNode()const { + return resource->source.node; + } operator bool() const{ return resource; } @@ -88,26 +88,30 @@ namespace api { enum class RenderPassNodeFlag : uint16_t { None = 0, - Input = 0x01, - Output = 0x02, + Output = 0x01, + FirstInput = 0x02, + LastOutput = 0x04, }; using RenderPassEdgeIterFn = std::function; struct RenderPassNode { Name name; - size_t hash; - RenderPassNodeType type; - RenderPassNodeFlag flag; + size_t hash{0}; + RenderPassNodeType type{0}; + RenderPassNodeFlag flag{0}; + bool isActive{ false }; RenderPassNodeExecuteFn executor; + pmr::vector dependencies{ FramePool() }; pmr::vector inEdges{ FramePool() }; pmr::vector outEdges{ FramePool() }; void ForeachEdge(RenderPassEdgeIterFn fn); - bool IsInput() { return any(flag & RenderPassNodeFlag::Input); } bool IsOutput() { return any(flag & RenderPassNodeFlag::Output); } + bool IsFirstInput() { return any(flag & RenderPassNodeFlag::FirstInput); } + bool IsLastOutput() { return any(flag & RenderPassNodeFlag::LastOutput); } FrameGraphEdgePtr GetInput(int i) { return inEdges[i]; }; FrameGraphEdgePtr GetOutput(int i) { return outEdges[i]; }; FrameGraphEdgePtr FindInput(Name name) { - for (auto edge : inEdges) { + for (auto& edge : inEdges) { if (edge.resource->name == name) { return edge; } @@ -116,7 +120,7 @@ namespace api { } FrameGraphEdgePtr FindOutput(Name name) { - for (auto edge : outEdges) { + for (auto& edge : outEdges) { if (edge.resource->name == name) { return edge; } @@ -124,13 +128,13 @@ namespace api { return {}; } }; - inline FrameGraphNodePtr::FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type) - : ref(ref), type(type) + inline FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type) + : type(type) { node = new (FramePool()) RenderPassNode(); node->executor = executor; } - inline size_t RenderPassContext::PassKey() + inline size_t RenderPassContext::PassKey()const { return node->hash; } diff --git a/engine/modules/engine/render/include/render/type.h b/engine/modules/engine/render/include/render/type.h index 38a0c1f..83ccb71 100644 --- a/engine/modules/engine/render/include/render/type.h +++ b/engine/modules/engine/render/include/render/type.h @@ -126,7 +126,7 @@ namespace api { operator bool() { return pResource; } - MaterialResource* FindMaterialResource(Name name) { + MaterialResource* FindMaterialResource(Name name) const { for (uint32_t i = 0; i < count; i++) { MaterialResource* res = (pResource + i); if (res->name == name) { @@ -135,7 +135,7 @@ namespace api { } return nullptr; } - void Upload(void** ppMappingAddr) { + void Upload(void** ppMappingAddr) const { for (uint32_t i = 0; i < count; i++) { auto res = pResource[i]; if (res.isDirty || res.isUnique) { @@ -186,7 +186,7 @@ namespace api { static BufferDesc Make() { return {}; } - BufferBarrier ToBarrier(ResourceState from, ResourceState to); + BufferBarrier ToBarrier(ResourceState from, ResourceState to)const; }; struct TextureViewDesc { ImagePtr image; @@ -219,7 +219,7 @@ namespace api { desc.dimension = dimension; return desc; } - TextureBarrier ToBarrier(ResourceState from, ResourceState to); + TextureBarrier ToBarrier(ResourceState from, ResourceState to)const; }; struct AttachmentDesc { ImagePtr image; @@ -233,6 +233,9 @@ namespace api { width = desc.width; height = desc.height; image = desc.image; + sampleCount = desc.sampleCount; + colorFormat = desc.format; + dimension = desc.dimension; return *this; } TextureDesc ToTexture() const { @@ -253,7 +256,7 @@ namespace api { desc.dimension = dimension; return desc; } - TextureBarrier ToBarrier(ResourceState from, ResourceState to); + TextureBarrier ToBarrier(ResourceState from, ResourceState to)const; }; struct TextureBarrier { @@ -286,29 +289,52 @@ namespace api { const TextureBarrier* pTextureBarriers; uint32_t textureBarriersCount; }; - inline BufferBarrier BufferDesc::ToBarrier(ResourceState from, ResourceState to) + inline BufferBarrier BufferDesc::ToBarrier(ResourceState from, ResourceState to)const { - BufferBarrier barrier; + BufferBarrier barrier{}; barrier.mSrcState = from; barrier.mDstState = to; return barrier; } - inline TextureBarrier TextureDesc::ToBarrier(ResourceState from, ResourceState to) + inline TextureBarrier TextureDesc::ToBarrier(ResourceState from, ResourceState to)const { - TextureBarrier barrier; + TextureBarrier barrier{}; barrier.mSrcState = from; barrier.mDstState = to; barrier.mTexture = *this; return barrier; } - inline TextureBarrier AttachmentDesc::ToBarrier(ResourceState from, ResourceState to) + inline TextureBarrier AttachmentDesc::ToBarrier(ResourceState from, ResourceState to)const { - TextureBarrier barrier; + TextureBarrier barrier{}; barrier.mSrcState = from; barrier.mDstState = to; barrier.mTexture = ToTexture(); return barrier; } + inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) { + if (k1.image != k2.image) return false; + if (k1.format != k2.format) return false; + if (k1.dimension != k2.dimension) return false; + if (k1.baseArrayLayer != k2.baseArrayLayer) return false; + if (k1.layerCount != k2.layerCount) return false; + if (k1.baseMipLevel != k2.baseMipLevel) return false; + if (k1.levelCount != k2.levelCount) return false; + return true; + } + inline bool operator==(const TextureDesc& k1, const TextureDesc& k2) { + if (k1.image != k2.image) return false; + if (k1.format != k2.format) return false; + if (k1.dimension != k2.dimension) return false; + if (k1.state != k2.state) return false; + if (k1.width != k2.width) return false; + if (k1.height != k2.height) return false; + if (k1.arraySize != k2.arraySize) return false; + if (k1.mipLevel != k2.mipLevel) return false; + if (k1.sampleCount != k2.sampleCount) return false; + if (k1.depth != k2.depth) return false; + return true; + } } #include "meta/hash.h" namespace std { diff --git a/engine/modules/engine/render/src/graph/frame_graph.cpp b/engine/modules/engine/render/src/graph/frame_graph.cpp index ae17347..c6fdd7b 100644 --- a/engine/modules/engine/render/src/graph/frame_graph.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph.cpp @@ -1,32 +1,12 @@ #include "render/graph/frame_graph.h" #include "render/renderapi.h" +#include +#include +#include namespace api { - inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) { - if (k1.image != k2.image) return false; - if (k1.format != k2.format) return false; - if (k1.dimension != k2.dimension) return false; - if (k1.baseArrayLayer != k2.baseArrayLayer) return false; - if (k1.layerCount != k2.layerCount) return false; - if (k1.baseMipLevel != k2.baseMipLevel) return false; - if (k1.levelCount != k2.levelCount) return false; - return true; - } - inline bool operator==(const TextureDesc& k1, const TextureDesc& k2) { - if (k1.image != k2.image) return false; - if (k1.format != k2.format) return false; - if (k1.dimension != k2.dimension) return false; - if (k1.state != k2.state) return false; - if (k1.width != k2.width) return false; - if (k1.height != k2.height) return false; - if (k1.arraySize != k2.arraySize) return false; - if (k1.mipLevel != k2.mipLevel) return false; - if (k1.sampleCount != k2.sampleCount) return false; - if (k1.depth != k2.depth) return false; - return true; - } FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor) { - FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor }; + FrameGraphNodePtr node_ptr{executor }; RenderPassBuilder builder{ this, node_ptr }; setup(*this, builder); mNodes.push_back(node_ptr); @@ -36,7 +16,7 @@ namespace api { { return TextureBuilder{this}; } - void FrameGraph::InitSurface(const pmr::vector& surfaces) + void FrameGraph::InitSurface(span surfaces) { mSurface = surfaces[0]; RenderAPI* API = RenderAPI::Ptr(); @@ -48,18 +28,79 @@ namespace api { } void FrameGraph::Compile() { - auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) { - int degree = 0; - for (lemon::ListGraph::IncEdgeIt e(mGraph, node.ref); e != lemon::INVALID; ++e) { - ++degree; + CullGraph(); + FillGraph(); + } + void FrameGraph::CullGraph() + { + pmr::vector outputNodes{FramePool()}; + std::stack stack; + for (auto& node : mNodes) { + if (node->IsOutput()) { + stack.push(node.node); + outputNodes.push_back(node.node); + if ((!mLastOutputNode || node->type > mLastOutputNode->type)) { + mLastOutputNode = node.node; + } } - return !degree; + } + while (!stack.empty()) { + RenderPassNode* node = stack.top(); + stack.pop(); + if (node->isActive) { + continue; + } + node->isActive = true; + bool isInput = node->IsOutput(); + for (auto& edge : node->inEdges) { + if (!edge->source->isActive) { + stack.push(edge.SourceNode()); + } + isInput = isInput || edge->name == NameSurface; + } + if (isInput && (!mFirstInputNode || node->type < mFirstInputNode->type)) { + mFirstInputNode = node; + } + } + auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) { + return !node->isActive; }); - //mNodes.erase(end, mNodes.end()); + mNodes.erase(end, mNodes.end()); + if (outputNodes.size() > 1) { + std::sort(outputNodes.begin(), outputNodes.end(), [](RenderPassNode* a, RenderPassNode* b) { + if (a->type != b->type) { + return a->type < b->type; + } + return a < b; + }); + for (size_t i = 1; i < outputNodes.size(); ++i) { + outputNodes[i]->dependencies.push_back(outputNodes[i - 1]); + } + } + } + void FrameGraph::FillGraph() + { + std::pmr::unordered_set seenNodes{FramePool()}; + for (auto& node : mNodes) { + if (!node->dependencies.empty()) { + seenNodes.insert(node->dependencies[0]); + } + for (auto& edge : node->inEdges) { + RenderPassNode* srcNode = edge.SourceNode(); + if (seenNodes.insert(srcNode).second) { + node->dependencies.push_back(srcNode); + } + } + seenNodes.clear(); + } + if (mLastOutputNode) { + mFirstInputNode->flag |= RenderPassNodeFlag::FirstInput; + mLastOutputNode->flag |= RenderPassNodeFlag::LastOutput; + } } void FrameGraph::Execute(FRenderView& view) { - for (auto node : mNodes) { + for (auto& node : mNodes) { switch (node.type) { case RenderPassType::Render: ExecuteRenderPass(node.node, view); @@ -78,8 +119,9 @@ namespace api { } void FrameGraph::Clear() { - mGraph.clear(); mNodes.clear(); + mFirstInputNode = nullptr; + mLastOutputNode = nullptr; } void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view) { diff --git a/engine/modules/engine/render/src/graph/frame_graph_builder.cpp b/engine/modules/engine/render/src/graph/frame_graph_builder.cpp index 0ecfd0c..194b2f5 100644 --- a/engine/modules/engine/render/src/graph/frame_graph_builder.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph_builder.cpp @@ -51,8 +51,6 @@ namespace api { FrameGraphEdgePtr edge{ refEdge , state}; node->inEdges.emplace_back(edge); refEdge->targets.emplace_back(node); - if(refEdge->source) - graph.mGraph.addEdge(refEdge->source.ref, node.ref); return *this; } FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state) @@ -61,15 +59,12 @@ namespace api { FrameGraphEdgePtr edge{ refEdge , state }; node->outEdges.emplace_back(edge); refEdge->targets.emplace_back(node); - if (refEdge->source) - graph.mGraph.addEdge(node.ref, refEdge->source.ref); return *this; } - FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc, ResourceState state) + FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc) { edge->name = name; edge->resource = desc; - edge.targetState = state; return *this; } } \ No newline at end of file diff --git a/engine/modules/engine/render/src/pass/demo_pass.cpp b/engine/modules/engine/render/src/pass/demo_pass.cpp index 54bb63f..f6aca5f 100644 --- a/engine/modules/engine/render/src/pass/demo_pass.cpp +++ b/engine/modules/engine/render/src/pass/demo_pass.cpp @@ -13,15 +13,12 @@ namespace api { { AttachmentDesc surface{}; surface.FromTexture(graph.mSurface); - surface.colorFormat = TinyImageFormat_B8G8R8A8_SRGB; - surface.sampleCount = SAMPLE_COUNT_1; - surface.dimension = TextureDimension::TEX_2D; auto edge = graph.CreateTextureBuild() - .Import(FrameGraph::NameSurface, surface, ResourceState::COLOR_ATTACHMENT) + .Import(FrameGraph::NameSurface, surface) .Edge(); builder.Name("MiniPass") - .Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Input | RenderPassNodeFlag::Output) - .Write(edge, edge.targetState); + .Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Output) + .Write(edge, ResourceState::COLOR_ATTACHMENT); } void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx) { diff --git a/engine/modules/engine/render/xmake.lua b/engine/modules/engine/render/xmake.lua index 40ecdb3..b126fa6 100644 --- a/engine/modules/engine/render/xmake.lua +++ b/engine/modules/engine/render/xmake.lua @@ -7,7 +7,7 @@ static_component("render","engine") add_files("src/**.cpp", "3rdparty/imgui/*.cpp") add_deps("asset", "zlib", "core") add_syslinks("user32", {public = true}) - add_packages("lemon", "libsdl","shaderc","spirv-cross", {public = true}) + add_packages("libsdl","shaderc","spirv-cross", {public = true}) if WITH_EDITOR then add_defines("WITH_EDITOR", {public = true}) add_packages("imgui",{public = true}) diff --git a/engine/modules/engine/zlib/include/pmr/name.h b/engine/modules/engine/zlib/include/pmr/name.h index f15971c..e317754 100644 --- a/engine/modules/engine/zlib/include/pmr/name.h +++ b/engine/modules/engine/zlib/include/pmr/name.h @@ -93,7 +93,7 @@ namespace pmr { stringEntryHeader.Init((Hi >> 8u) & STRING_HASH_PROBE_MASK, view.size()); data = view.data(); } - const char* GetData() { + const char* GetData() const { return data; } uint32_t GetSlotIndex() const{ @@ -140,9 +140,9 @@ namespace pmr { static constexpr double SLOT_POOL_RESIZE_USAGE_RATE = 0.9; static constexpr uint32_t SLOT_POOL_INITIALIZE_SIZE = 256u; private: - uint32_t capcity; - uint32_t size; - Slot* slotArray; + uint32_t capcity{0}; + uint32_t size{0}; + Slot* slotArray{ nullptr }; std::mutex mutex; public: Slot& FindUnusedOrTargetSlot(HashInfo hashInfo); diff --git a/engine/modules/engine/zlib/include/refl/detail/any.inl b/engine/modules/engine/zlib/include/refl/detail/any.inl index e8109a4..5bf6dcf 100644 --- a/engine/modules/engine/zlib/include/refl/detail/any.inl +++ b/engine/modules/engine/zlib/include/refl/detail/any.inl @@ -48,7 +48,7 @@ namespace refl{ { Any to{ ptr, cls }; auto fieldList = cls->GetFields(refl::FIND_ALL_MEMBER, Name("")); - for (auto field : fieldList) { + for (auto& field : fieldList) { Any obj = to.Member(field); Convert::Construct(obj, Member(field)); } diff --git a/engine/modules/engine/zlib/include/refl/detail/uclass.inl b/engine/modules/engine/zlib/include/refl/detail/uclass.inl index c30dc91..427e0f5 100644 --- a/engine/modules/engine/zlib/include/refl/detail/uclass.inl +++ b/engine/modules/engine/zlib/include/refl/detail/uclass.inl @@ -66,7 +66,7 @@ namespace refl { } else { MethodType fptr = (MethodType)field->data.method.fptr; - auto ret = ArgsList.front(); + auto& ret = ArgsList.front(); if (ret.cls == meta_info()) { *(R*)ret.ptr = fptr((param--->CastTo())...); } diff --git a/engine/modules/render/vulkan/include/vkn/type.h b/engine/modules/render/vulkan/include/vkn/type.h index eede67f..bcf1037 100644 --- a/engine/modules/render/vulkan/include/vkn/type.h +++ b/engine/modules/render/vulkan/include/vkn/type.h @@ -121,6 +121,17 @@ namespace vkn { uint32_t descCount = 0; bool inUse = false; }; + inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) { + if (k1.pass != k2.pass) return false; + if (k1.attachmentCount != k2.attachmentCount) return false; + for (int i = 0; i < k1.attachmentCount; i++) { + if (k1.imageViews[i] != k2.imageViews[i]) return false; + } + if (k1.height != k2.height) return false; + if (k1.width != k2.width) return false; + if (k1.layers != k2.layers) return false; + return true; + } } namespace std { template<> diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api.h b/engine/modules/render/vulkan/include/vkn/vulkan_api.h index 9b4575e..33d6241 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api.h @@ -43,6 +43,7 @@ namespace vkn { VkPipeline GetPipeline() { return nullptr; }; RenderPassInfo* GetRenderPassInfo(Name name, size_t hash); RenderPassInfo* GetRenderPassInfo(size_t& hash, const RenderPassKey& config); + void SetRenderPassInfo(Name name, VkRenderPass pass); Backend& GetBackend() { return backend; } diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_window.h b/engine/modules/render/vulkan/include/vkn/vulkan_window.h index a5b8cf0..9c42bfe 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_window.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_window.h @@ -23,7 +23,7 @@ namespace vkn { friend class VulkanWindow; Device& mDevice; VkSwapchainKHR mPtr; - int mFrames; + uint32_t mFrames; pmr::vector mSurfaces{ GlobalPool() }; pmr::vector mCommands{ GlobalPool() }; pmr::vector mFences{ GlobalPool() }; @@ -32,7 +32,7 @@ namespace vkn { VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); void Aquire(VulkanContext& ctx); void Present(VulkanContext& ctx); - int FrameCount() { + int FrameCount() const { return mFrames; } const pmr::vector& GetSurface() { diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index d08c3ff..13ce81c 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -11,17 +11,6 @@ #include "zlog.h" namespace vkn { using api::EventSystem; - inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) { - if (k1.pass != k2.pass) return false; - if (k1.attachmentCount != k2.attachmentCount) return false; - for (int i = 0; i < k1.attachmentCount; i++) { - if (k1.imageViews[i] != k2.imageViews[i]) return false; - } - if (k1.height != k2.height) return false; - if (k1.width != k2.width) return false; - if (k1.layers != k2.layers) return false; - return true; - } VulkanAPI::VulkanAPI() : RenderAPI(new VulkanContext()) , window(*VulkanWindow::Ptr()) , backend(VulkanEngineName) @@ -447,16 +436,16 @@ namespace vkn { VkSemaphore waitSemaphores[8]; VkPipelineStageFlags waitDstStageMasks[8]; uint32_t semaphoreCount = 0; - if (node->IsInput()) { + if (node->IsFirstInput()) { waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore; - zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore); + //zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore); } - for (auto& it : node->inEdges) { - RenderPassInfo* inputInfo = GetRenderPassInfo(it->source->name ,it->source->hash); + for (auto& it : node->dependencies) { + RenderPassInfo* inputInfo = GetRenderPassInfo(it->name ,it->hash); waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitSemaphores[semaphoreCount++] = inputInfo->semaphores[context.frame]; - zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]); + //zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]); } VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -467,10 +456,10 @@ namespace vkn { submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitDstStageMasks; submitInfo.waitSemaphoreCount = semaphoreCount; - if (node->IsOutput()) { + if (node->IsLastOutput()) { ctx.graphSemaphore = passInfo->semaphores[context.frame]; } - zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]); + //zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]); vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr); } RenderPassInfo* VulkanAPI::GetRenderPassInfo(Name name, size_t hash) { @@ -665,4 +654,11 @@ namespace vkn { RenderPassCache.emplace(hash, info); return &RenderPassCache[hash]; } + void VulkanAPI::SetRenderPassInfo(Name name, VkRenderPass pass) { + RenderPassInfo info{}; + info.config.pass = pass; + backend.GetDevice().CreateSemaphores(info.semaphores, context.frameCount); + Backend::RenderWorker->GetCommandPool().PopList(info.commands, context.frameCount); + RenderPassNameCache.emplace(name, info); + } } diff --git a/engine/modules/render/vulkan/src/vulkan_context.cpp b/engine/modules/render/vulkan/src/vulkan_context.cpp index 7f16b25..09a5f63 100644 --- a/engine/modules/render/vulkan/src/vulkan_context.cpp +++ b/engine/modules/render/vulkan/src/vulkan_context.cpp @@ -76,8 +76,8 @@ namespace vkn { submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]); - zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]); + //zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]); + //zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]); vkQueueSubmit(queue, 1, &submitInfo, surfaceFence); graphSemaphore = nullptr; } diff --git a/engine/modules/render/vulkan/src/vulkan_imgui.cpp b/engine/modules/render/vulkan/src/vulkan_imgui.cpp index da96927..d991539 100644 --- a/engine/modules/render/vulkan/src/vulkan_imgui.cpp +++ b/engine/modules/render/vulkan/src/vulkan_imgui.cpp @@ -11,13 +11,9 @@ #include "event/event_system.h" #include "tinyimageformat/tinyimageformat_apis.h" namespace vkn { - using api::EventSystem; + using namespace api; + static Name ImguiPassName{"ImguiPass"}; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; - static VkRenderPass g_RenderPass = VK_NULL_HANDLE; - static VkCommandPool g_CommandPool = VK_NULL_HANDLE; - static std::vector g_CommandBuffers; - static std::vector g_FrameBuffers; - static std::vector g_RenderFinishSemaphores; VkDescriptorPool CreateDescriptorPool(VkDevice device) { VkDescriptorPoolSize pool_sizes[] = { @@ -84,59 +80,6 @@ namespace vkn { throw std::runtime_error("Could not create Dear ImGui's render pass"); return renderPass; } - void CreateFrameBuffer(VulkanAPI* API, VkRenderPass renderPass, const pmr::vector& surfaces) { - VkDevice device = API->GetBackend().GetDevice().Ptr(); - g_FrameBuffers.resize(surfaces.size()); - VkFramebuffer* framebuffer = g_FrameBuffers.data(); - for (auto& surface : surfaces) - { - VkFramebufferCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - info.renderPass = renderPass; - info.pAttachments = (VkImageView*)API->graph.ResolveTextureView(surface.ToTextureView()); - info.attachmentCount = 1; - info.width = surface.width; - info.height = surface.height; - info.layers = 1; - vkCreateFramebuffer(device, &info, VK_NULL_HANDLE, framebuffer++); - } - } - void CreateCommandPool(VkDevice device, int queueFamilyIndex, int frames) { - VkCommandPool commandPool; - // 创建一个专用的CommandPool - { - VkCommandPoolCreateInfo commandPoolCreateInfo = {}; - commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; - commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - - if (vkCreateCommandPool(device, &commandPoolCreateInfo, VK_NULL_HANDLE, &commandPool) != VK_SUCCESS) - throw std::runtime_error("Could not create graphics command pool"); - } - - // 创建专用的CommandBuffer - { - g_CommandBuffers.resize(frames); - - VkCommandBufferAllocateInfo allocInfo = {}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = commandPool; - allocInfo.commandBufferCount = frames; - - if (vkAllocateCommandBuffers(device, &allocInfo, g_CommandBuffers.data()) != VK_SUCCESS) - throw std::runtime_error("failed to allocate command buffers!"); - } - g_RenderFinishSemaphores.resize(frames); - - for (size_t i = 0; i < frames; i++) - { - VkSemaphoreCreateInfo semaphoreInfo = {}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &g_RenderFinishSemaphores[i]) != VK_SUCCESS) - throw std::runtime_error("failed to create synchronization objects for a frame!"); - } - } void VulkanImguiSystem::Initialize() { VulkanAPI* API = VulkanAPI::Ptr(); @@ -161,11 +104,7 @@ namespace vkn { init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = VK_NULL_HANDLE; ImGui_ImplVulkan_Init(&init_info); - - g_RenderPass = renderPass; - auto& surfaces = window->Swapchain()->GetSurface(); - //CreateFrameBuffer(API, renderPass, surfaces); - //CreateCommandPool(backend.GetDevice().Ptr(), pQueue->QueueFamilyIndex(), surfaces.size()); + API->SetRenderPassInfo(ImguiPassName, renderPass); EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiSystem::Render, this); } @@ -175,15 +114,22 @@ namespace vkn { } void VulkanImguiSystem::Render() { - if(false) - VulkanAPI::Ptr()->graph.AddRenderPass(); + VulkanAPI::Ptr()->graph.AddRenderPass(); } void VulkanImguiSystem::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) { - + AttachmentDesc surface{}; + surface.FromTexture(graph.mSurface); + auto edge = graph.CreateTextureBuild() + .Import(FrameGraph::NameSurface, surface) + .Edge(); + builder.Name(ImguiPassName) + .Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output) + .Write(edge, ResourceState::COLOR_ATTACHMENT); } - void VulkanImguiSystem::Execute(FrameGraph&, RenderPassContext&) + void VulkanImguiSystem::Execute(FrameGraph& graph, RenderPassContext& context) { + graph.mSurface.state = ResourceState::PRESENT; ImGui_ImplVulkan_NewFrame(); ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); @@ -194,53 +140,14 @@ namespace vkn { ImGui::End(); ImGui::Render(); - - - } - void EndEditorRender() - { - /* - VulkanAPI* API = VulkanAPI::Ptr(); - uint32_t frame = API->context.frame; - CommandBuffer commandBuffer = CommandBuffer(g_CommandBuffers[frame]); - commandBuffer.Reset(); - commandBuffer.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - - VkRenderPassBeginInfo renderPassinfo = {}; - renderPassinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassinfo.renderPass = g_RenderPass; - renderPassinfo.framebuffer = g_FrameBuffers[frame]; - renderPassinfo.renderArea.extent.width = API->graph.mSurface.width; - renderPassinfo.renderArea.extent.height = API->graph.mSurface.height; - renderPassinfo.clearValueCount = 0; - vkCmdBeginRenderPass(commandBuffer.Ptr(), &renderPassinfo, VK_SUBPASS_CONTENTS_INLINE); - // Record Imgui Draw Data and draw funcs into command buffer - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer.Ptr()); - vkCmdEndRenderPass(commandBuffer.Ptr()); - commandBuffer.EndRecord(); - - // 提交CommandBuffer - pmr::vector waitStages{FramePool()}; - waitStages.resize(renderAPI->curWaitSemaphores.size(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); - vector waitSemaphores = renderAPI->curWaitSemaphores; - - waitStages.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - waitSemaphores.push_back(renderAPI->presentImageAvailableSemaphores[renderAPI->currentFrame]); - - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pCommandBuffers = &commandBuffer.Ptr(); - submitInfo.commandBufferCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.pWaitDstStageMask = waitStages.data(); - submitInfo.waitSemaphoreCount = static_cast(waitSemaphores.size()); - submitInfo.pSignalSemaphores = &g_RenderFinishSemaphores[renderAPI->currentFrame]; - submitInfo.signalSemaphoreCount = 1; - - VkFence fence = renderAPI->inFlightFences[renderAPI->currentFrame]; - if (vkQueueSubmit(renderAPI->graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS) - throw std::runtime_error("failed to submit draw command buffer!"); - - renderAPI->curWaitSemaphores = { g_RenderFinishSemaphores[renderAPI->currentFrame] };*/ + VulkanContext& ctx = *(VulkanContext*)&context.parent; + ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), ctx.command); + ImGuiIO& io = ImGui::GetIO(); + // 更新并渲染平台窗口 + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(nullptr, ctx.command); + } } } diff --git a/engine/modules/render/vulkan/src/vulkan_window.cpp b/engine/modules/render/vulkan/src/vulkan_window.cpp index 5dbf982..545c62c 100644 --- a/engine/modules/render/vulkan/src/vulkan_window.cpp +++ b/engine/modules/render/vulkan/src/vulkan_window.cpp @@ -23,7 +23,7 @@ namespace vkn { args.height = mHeight; mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args); api->context.frameCount = args.frames; - api->graph.InitSurface(mSwapchain->mSurfaces); + api->graph.InitSurface(std::span{mSwapchain->mSurfaces.data(), args.frames}); return true; } VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args) @@ -63,7 +63,7 @@ namespace vkn { swapchain_images.resize(imageCount); vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data()); mFences.reserve(mFrames); - mSurfaces.reserve(mFrames); + mSurfaces.reserve(imageCount); mCommands.reserve(mFrames); mSemaphores.reserve(mFrames + mFrames); TextureDesc desc{}; @@ -75,6 +75,7 @@ namespace vkn { desc.arraySize = 1; desc.mipLevel = 1; desc.depth = 1; + desc.dimension = TextureDimension::TEX_2D; for (int i = 0; i < mFrames; i++) { desc.image = swapchain_images[i]; mSurfaces.push_back(desc); @@ -83,12 +84,15 @@ namespace vkn { mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY)); mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT)); } + for (int i = mFrames; i < imageCount; i++) { + desc.image = swapchain_images[i]; + mSurfaces.push_back(desc); + } } void VulkanSwapchain::Aquire(VulkanContext& ctx) { VkFence surfaceFence = mFences[ctx.frame]; VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame]; - ctx.surface = mSurfaces[ctx.frame]; ctx.surfaceCommand = mCommands[ctx.frame]; ctx.surfaceFence = surfaceFence; ctx.surfaceSemaphore = surfaceSemaphore; @@ -97,12 +101,12 @@ namespace vkn { throw std::runtime_error("Failed to wait for fence!"); vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame); vkResetFences(mDevice.Ptr(), 1, &surfaceFence); - ctx.presentFrame = ctx.presentFrame % mFrames; - zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore); + ctx.surface = mSurfaces[ctx.presentFrame]; + //zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore); } void VulkanSwapchain::Present(VulkanContext& ctx) { - zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore); + //zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore); VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.pWaitSemaphores = &ctx.presentSemaphore;