From fef024d407b3ed8ee0a1c745b880c4215e71b121 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Thu, 19 Dec 2024 17:23:52 +0800 Subject: [PATCH] rebuild framegraph resource system --- .../editor/panel/asset_preview_panel.h | 2 +- engine/include/editor/panel/menu_bar_panel.h | 2 +- .../editor/window/editor_main_window.h | 2 +- .../engine/app/include/data/engine_config.h | 4 + .../modules/engine/app/include/event/event.h | 2 +- .../engine/app/include/event/event_system.h | 3 +- .../tinyimageformat/tinyimageformat_base.h | 2 +- .../engine/render/impl/renderapi_impl.inl | 1 + .../render/include/render/editor_system.h | 10 +- .../render/include/render/graph/frame_graph.h | 44 ++-- .../render/graph/frame_graph_builder.inl | 26 +-- .../engine/render/include/render/graph/type.h | 68 ++---- .../render/include/render/pass/demo_pass.h | 2 +- .../engine/render/include/render/renderapi.h | 4 +- .../engine/render/include/render/type.h | 125 +++++------ .../engine/render/src/graph/frame_graph.cpp | 194 ++++++++++++------ .../render/src/graph/frame_graph_builder.cpp | 56 +---- .../modules/engine/render/src/graph/type.cpp | 18 +- .../engine/render/src/pass/demo_pass.cpp | 10 +- engine/modules/engine/zlib/include/pmr/name.h | 34 ++- .../vulkan/include/vkn/thread/buffer_worker.h | 5 + .../modules/render/vulkan/include/vkn/type.h | 2 +- .../render/vulkan/include/vkn/vulkan_api.h | 12 +- .../vulkan/include/vkn/vulkan_api_help.h | 3 +- .../vulkan/include/vkn/vulkan_imgui_editor.h | 12 +- .../render/vulkan/include/vkn/vulkan_window.h | 6 - .../vulkan/src/thread/buffer_worker.cpp | 9 + .../modules/render/vulkan/src/vulkan_api.cpp | 34 ++- .../render/vulkan/src/vulkan_api_help.cpp | 8 +- .../render/vulkan/src/vulkan_imgui_editor.cpp | 58 ++++-- .../render/vulkan/src/vulkan_window.cpp | 3 +- .../src/editor/panel/asset_preview_panel.cpp | 10 +- engine/src/editor/panel/menu_bar_panel.cpp | 2 +- .../src/editor/window/editor_main_window.cpp | 4 +- game/zworld/src/zworld.cpp | 4 +- 35 files changed, 424 insertions(+), 357 deletions(-) diff --git a/engine/include/editor/panel/asset_preview_panel.h b/engine/include/editor/panel/asset_preview_panel.h index aeef233..5a47440 100644 --- a/engine/include/editor/panel/asset_preview_panel.h +++ b/engine/include/editor/panel/asset_preview_panel.h @@ -3,6 +3,6 @@ namespace api { class AssetPreviewPanel : public EditorPanel{ public: - void DrawPanel() override; + void DrawPanel(FrameGraph& graph, RenderEditorContext& context) override; }; } \ No newline at end of file diff --git a/engine/include/editor/panel/menu_bar_panel.h b/engine/include/editor/panel/menu_bar_panel.h index 379fa39..eca011e 100644 --- a/engine/include/editor/panel/menu_bar_panel.h +++ b/engine/include/editor/panel/menu_bar_panel.h @@ -3,6 +3,6 @@ namespace api { class MenuBarPanel : public EditorPanel { public: - void DrawPanel() override; + void DrawPanel(FrameGraph& graph, RenderEditorContext& context) override; }; } \ No newline at end of file diff --git a/engine/include/editor/window/editor_main_window.h b/engine/include/editor/window/editor_main_window.h index 48a38b2..098a319 100644 --- a/engine/include/editor/window/editor_main_window.h +++ b/engine/include/editor/window/editor_main_window.h @@ -4,6 +4,6 @@ namespace api { class EditorMainWindow : public EditorWindow { public: EditorMainWindow(); - void Draw() override; + void Draw(FrameGraph& graph, RenderEditorContext& context) override; }; } \ No newline at end of file diff --git a/engine/modules/engine/app/include/data/engine_config.h b/engine/modules/engine/app/include/data/engine_config.h index 84da196..e590e22 100644 --- a/engine/modules/engine/app/include/data/engine_config.h +++ b/engine/modules/engine/app/include/data/engine_config.h @@ -3,5 +3,9 @@ namespace api{ struct EngineConfig { GraphicsAPI API = GraphicsAPI::Vulkan; +#ifdef WITH_EDITOR + bool IsRenderEditorSurface = false; +#endif // WITH_EDITOR + }; } \ No newline at end of file diff --git a/engine/modules/engine/app/include/event/event.h b/engine/modules/engine/app/include/event/event.h index d343f84..e29e819 100644 --- a/engine/modules/engine/app/include/event/event.h +++ b/engine/modules/engine/app/include/event/event.h @@ -22,7 +22,7 @@ namespace api{ static std::function EasyBind(R(Type::* func)(Args... args) const, const Type* invoker) { return [=](auto&&... args) { return (invoker->*func)(std::forward(args)...); - }; + }; } public: Event(Name name) : name(name){}; diff --git a/engine/modules/engine/app/include/event/event_system.h b/engine/modules/engine/app/include/event/event_system.h index 9364156..361bab7 100644 --- a/engine/modules/engine/app/include/event/event_system.h +++ b/engine/modules/engine/app/include/event/event_system.h @@ -2,12 +2,13 @@ #include "event.h" #include "module/module.h" namespace api { + class FrameGraph; class APP_API EventSystem : public ISystem{ SINGLETON_IMPL(EventSystem) public: EventSystem(); void Initialize() override; void Finalize() override; - Event BeginRenderFrame{"BeginRenderFrame"}; + Event BeginRenderFrame{"BeginRenderFrame"}; }; } \ No newline at end of file diff --git a/engine/modules/engine/render/3rdparty/tinyimageformat/tinyimageformat_base.h b/engine/modules/engine/render/3rdparty/tinyimageformat/tinyimageformat_base.h index ba86991..53d4f13 100644 --- a/engine/modules/engine/render/3rdparty/tinyimageformat/tinyimageformat_base.h +++ b/engine/modules/engine/render/3rdparty/tinyimageformat/tinyimageformat_base.h @@ -229,7 +229,7 @@ * * */ -typedef enum TinyImageFormat { +typedef enum TinyImageFormat : uint8_t{ TinyImageFormat_UNDEFINED = 0, TinyImageFormat_R1_UNORM = 1, TinyImageFormat_R2_UNORM = 2, diff --git a/engine/modules/engine/render/impl/renderapi_impl.inl b/engine/modules/engine/render/impl/renderapi_impl.inl index 2dc6531..ed80342 100644 --- a/engine/modules/engine/render/impl/renderapi_impl.inl +++ b/engine/modules/engine/render/impl/renderapi_impl.inl @@ -22,6 +22,7 @@ namespace api { } void RenderAPI::Render() { + graph.Setup(); for (auto view : context.views) { RenderView(view); } diff --git a/engine/modules/engine/render/include/render/editor_system.h b/engine/modules/engine/render/include/render/editor_system.h index 4017849..7b84ecf 100644 --- a/engine/modules/engine/render/include/render/editor_system.h +++ b/engine/modules/engine/render/include/render/editor_system.h @@ -1,12 +1,17 @@ #pragma once #ifdef WITH_EDITOR +#include "graph/frame_graph.h" #include "module/module_manager.h" +#include namespace api { + class RenderEditorContext { + + }; class EditorPanel { public: EditorPanel() = default; ~EditorPanel() = default; - virtual void DrawPanel() = 0; + virtual void DrawPanel(FrameGraph& graph, RenderEditorContext& ctx) = 0; }; class EditorWindow { protected: @@ -14,7 +19,7 @@ namespace api { public: EditorWindow() = default; ~EditorWindow() = default; - virtual void Draw() = 0; + virtual void Draw(FrameGraph& graph, RenderEditorContext& ctx) = 0; template T* AddPanel(Args&&... args) { T* ptr = new (GlobalPool()) T(std::forward(args)...); @@ -35,6 +40,7 @@ namespace api { mWindows.push_back(ptr); return ptr; } + virtual ImTextureID AddTexture(const TextureDesc& desc) = 0; }; } #endif // WITH_EDITOR \ No newline at end of file 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 6d108c6..80714ff 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph.h @@ -2,37 +2,47 @@ #include "type.h" namespace api { struct FRenderView; + using pmr::Tag; class FrameGraph { public: - class TextureBuilder; - class RenderPassBuilder; - public: - inline static Name NameSurface{ "surface" }; + TextureDesc mSurface{}; + table mTextureTagMap; + table mTextureKeyMap; + std::vector mTexturePool; + table mTextureViewPool; + pmr::vector mNodes{FramePool()}; RenderPassNode* mFirstInputNode{ nullptr }; RenderPassNode* mLastOutputNode{ nullptr }; - TextureDesc mSurface; - table mTextureTable; - table mTexturePool; - table mTextureViewPool; - pmr::vector mNodes{FramePool()}; + inline static Name NameSurface{ "surface" }; +#ifdef WITH_EDITOR + inline static Name NameEditorSurface{ "editor_surface" }; + TextureDesc mEditorSurface{}; + bool mIsRenderEditorSurface{false}; +#endif // public: template FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); } - using RenderPassSetupFunction = std::function; FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor); - TextureBuilder CreateTextureBuild(); - void InitSurface(span surfaces); + RenderPassBuilder CreateRenderPassBuild(); + void InitSurface(TextureDesc* surfaces, uint32_t frames); + void Input(const TextureDesc& surfaces) { mSurface = surfaces; }; + void Setup(); 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); - ImagePtr ResolveTexture(TextureDesc desc); - ImageViewPtr ResolveTextureView(TextureViewDesc desc); + void TransitionState(TextureDesc& desc, ResourceState state); + bool ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate); + bool ResolveState(AttachmentDesc& desc, ResourceState& srcstart, ResourceState& dststate); + bool ResolveState(BufferDesc& desc, ResourceState& srcstart, ResourceState& dststate); + TextureDesc& ResolveTexture(TextureDesc& desc); + TextureDesc ResourceTexture(Name name, int num); + ImageViewPtr ResolveTextureView(TextureDesc& desc); + ImageViewPtr ResolveTextureView(TextureViewKey key); + void ResourceTexture(TextureDesc& desc); + void SetResourceTexture(TextureDesc texture, Name name, int num = 0); public: void ExecutePresentPass(FRenderView& view); void ExecuteRenderPass(RenderPassNode* node, FRenderView& view); 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 e6702ff..629943a 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 @@ -1,26 +1,16 @@ #pragma once namespace api { - struct FrameGraph::RenderPassBuilder { + struct RenderPassBuilder { FrameGraph& graph; - FrameGraphNodePtr& node; - FrameResource* resource; + FrameGraphNodePtr node; + FrameResource* resource{nullptr}; public: + RenderPassBuilder(FrameGraph* graph) noexcept + : graph(*graph), node() {}; RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept : graph(*graph) , node(node) {}; - FrameGraph::RenderPassBuilder& Name(pmr::Name name); - FrameGraph::RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None); - FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state); - FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state); - FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state); - FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& refEdge, ResourceState state); - FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& refEdge, ResourceState state); - }; - struct FrameGraph::TextureBuilder { - FrameGraph& graph; - FrameGraphEdgePtr edge; - public: - TextureBuilder(FrameGraph* graph)noexcept : graph(*graph) { edge.Make(); }; - FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc); - FrameGraphEdgePtr Edge() const { return edge; } + RenderPassBuilder& Name(pmr::Name name); + RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None); + RenderPassBuilder& Write(AttachmentDesc desc, ResourceState state, pmr::Name name = {}); }; } \ 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 7c24552..93a0633 100644 --- a/engine/modules/engine/render/include/render/graph/type.h +++ b/engine/modules/engine/render/include/render/graph/type.h @@ -3,6 +3,8 @@ #include "render/type.h" #include namespace api { + class FrameGraph; + class RenderPassBuilder; struct RenderPassNode; struct RenderContext; struct ComputePassContext {}; @@ -16,20 +18,17 @@ namespace api { size_t PassKey()const; }; struct CopyPassContext {}; - - class FrameGraph; + using RenderPassSetupFunction = std::function; using CopyPassExecuteFunction = std::function; using ComputePassExecuteFunction = std::function; using RenderPassExecuteFunction = std::function; using RenderPassNodeExecuteFn = std::variant; - class RenderPass; - class RenderPassNode; struct FrameGraphNodePtr { using NodeType = RenderPassType; RenderPassNode* node; NodeType type{ NodeType::Render }; FrameGraphNodePtr() : node(nullptr){}; - FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); + FrameGraphNodePtr(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); operator bool() const { return node; } @@ -40,65 +39,48 @@ namespace api { struct FrameResource { using Resource = std::variant; Name name; - Resource resource; - FrameGraphNodePtr source; - pmr::vector targets{ FramePool() }; + Resource res; + RenderPassNode* node; + FrameResource() noexcept = default; + FrameResource(Name name,const Resource& res, RenderPassNode* node) : name(name), res(res), node(node){}; template T& CastTo() { - return std::get(resource); + return std::get(res); } bool IsAttachment() const { - return std::holds_alternative(resource); + return std::holds_alternative(res); } bool IsTexture() const{ - return std::holds_alternative(resource); + return std::holds_alternative(res); } bool IsBuffer() const { - return std::holds_alternative(resource); + return std::holds_alternative(res); + } + static FrameResource* Make(Name name, const Resource& res, RenderPassNode* node) { + return new(FramePool()) FrameResource(name, res, node); } }; - struct FrameGraphEdgePtr { - ResourceState targetState; - FrameResource* resource; - FrameGraphEdgePtr() = default; - FrameGraphEdgePtr(const FrameGraphEdgePtr& edge, ResourceState state) { - targetState = state; - resource = edge.resource; - } - FrameResource* Make() { - resource = new (FramePool()) FrameResource(); - return resource; - } - RenderPassNode* SourceNode()const { - return resource->source.node; - } - operator bool() const{ - return resource; - } - FrameResource* operator ->()const { - return resource; - } - void ResolveView(FrameGraph* graph); - }; - enum class RenderPassNodeType : uint16_t { + using FrameGraphEdgePtr = FrameResource*; + enum class RenderPassNodeType : uint8_t { None, Scene, Imgui, }; - enum class RenderPassNodeFlag : uint16_t + enum class RenderPassNodeFlag : uint8_t { None = 0, Output = 0x01, FirstInput = 0x02, LastOutput = 0x04, }; - using RenderPassEdgeIterFn = std::function; + using RenderPassEdgeIterFn = std::function; struct RenderPassNode { Name name; size_t hash{0}; RenderPassNodeType type{0}; RenderPassNodeFlag flag{0}; bool isActive{ false }; + RenderPassSetupFunction setup; RenderPassNodeExecuteFn executor; pmr::vector dependencies{ FramePool() }; pmr::vector inEdges{ FramePool() }; @@ -112,7 +94,7 @@ namespace api { FrameGraphEdgePtr FindInput(Name name) { for (auto& edge : inEdges) { - if (edge.resource->name == name) { + if (edge->name == name) { return edge; } } @@ -121,19 +103,13 @@ namespace api { FrameGraphEdgePtr FindOutput(Name name) { for (auto& edge : outEdges) { - if (edge.resource->name == name) { + if (edge->name == name) { return edge; } } return {}; } }; - inline FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type) - : type(type) - { - node = new (FramePool()) RenderPassNode(); - node->executor = executor; - } inline size_t RenderPassContext::PassKey()const { return node->hash; diff --git a/engine/modules/engine/render/include/render/pass/demo_pass.h b/engine/modules/engine/render/include/render/pass/demo_pass.h index 9896d70..3cb2657 100644 --- a/engine/modules/engine/render/include/render/pass/demo_pass.h +++ b/engine/modules/engine/render/include/render/pass/demo_pass.h @@ -4,7 +4,7 @@ namespace api { class DemoPass : public RenderPass { public: - static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder); + static void Setup(FrameGraph& graph, RenderPassBuilder& builder); static void Execute(FrameGraph&, RenderPassContext&); }; diff --git a/engine/modules/engine/render/include/render/renderapi.h b/engine/modules/engine/render/include/render/renderapi.h index 97ef4cb..5a04eb7 100644 --- a/engine/modules/engine/render/include/render/renderapi.h +++ b/engine/modules/engine/render/include/render/renderapi.h @@ -33,8 +33,8 @@ namespace api { virtual void LoadShader(Shader& shader, size_t passKey) = 0; virtual void CreateBuffer(BufferDesc& desc) = 0; - virtual ImagePtr CreateTexture(TextureDesc desc) = 0; - virtual ImageViewPtr CreateTextureView(TextureViewDesc desc) = 0; + virtual void CreateTexture(TextureDesc& desc) = 0; + virtual ImageViewPtr CreateTextureView(TextureViewKey desc) = 0; virtual void BeginFrame() = 0; virtual void EndFrame() = 0; diff --git a/engine/modules/engine/render/include/render/type.h b/engine/modules/engine/render/include/render/type.h index 83ccb71..ec07d5f 100644 --- a/engine/modules/engine/render/include/render/type.h +++ b/engine/modules/engine/render/include/render/type.h @@ -6,7 +6,7 @@ //#include namespace api { using pmr::Name; - enum class GraphicsAPI + enum class GraphicsAPI : uint8_t { OpenGL, Vulkan, @@ -18,14 +18,14 @@ namespace api { Compute, Copy }; - enum class BufferUsage { + enum class BufferUsage : uint8_t { STATIC = 0x01, //!< content modified once, used many times DYNAMIC = 0x02, //!< content modified frequently, used many times VERTEX = 0x04, UNIFORM = 0x08, SHADER_STORAGE = 0x10 }; - enum class ResourceMemoryUsage + enum class ResourceMemoryUsage : uint8_t { /// No intended memory usage specified. UNKNOWN = 0, @@ -39,7 +39,7 @@ namespace api { GPU_TO_CPU = 4, COUNT, }; - enum SampleCount + enum SampleCount : uint8_t { SAMPLE_COUNT_1 = 1, SAMPLE_COUNT_2 = 2, @@ -66,7 +66,7 @@ namespace api { DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected. ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected. }; - enum class ResourceState + enum class ResourceState : uint8_t { // The initial layout after the creation of the VkImage. We use this to denote the state before // any transition. @@ -89,7 +89,20 @@ namespace api { // TODO: explore separate layout policies for attachment+sampling and just attachment. COLOR_ATTACHMENT, }; - enum class TextureDimension + enum class TextureUsage :uint16_t { + NONE = 0x0000, + COLOR_ATTACHMENT = 0x0001, //!< Texture can be used as a color attachment + DEPTH_ATTACHMENT = 0x0002, //!< Texture can be used as a depth attachment + STENCIL_ATTACHMENT = 0x0004, //!< Texture can be used as a stencil attachment + UPLOADABLE = 0x0008, //!< Data can be uploaded into this texture (default) + SAMPLEABLE = 0x0010, //!< Texture can be sampled (default) + SUBPASS_INPUT = 0x0020, //!< Texture can be used as a subpass input + BLIT_SRC = 0x0040, //!< Texture can be used the source of a blit() + BLIT_DST = 0x0080, //!< Texture can be used the destination of a blit() + PROTECTED = 0x0100, //!< Texture can be used for protected content + DEFAULT = UPLOADABLE | SAMPLEABLE //!< Default texture usage + }; + enum class TextureDimension : uint8_t { TEX_NULL = 0, TEX_1D = 0x01, @@ -101,7 +114,7 @@ namespace api { UNIFORM_BUFFER, SAMPLER, }; - enum class ShaderStage : uint32_t { + enum class ShaderStage : uint8_t { NONE = 0, VERTEX = 0x1, FRAGMENT = 0x2, @@ -188,28 +201,33 @@ namespace api { } BufferBarrier ToBarrier(ResourceState from, ResourceState to)const; }; - struct TextureViewDesc { + struct TextureViewKey { ImagePtr image; - TinyImageFormat format : 16; - TextureDimension dimension : 8; - uint32_t baseArrayLayer : 8; - uint32_t layerCount : 8; - uint32_t baseMipLevel : 8; - uint32_t levelCount : 8; + TinyImageFormat format; + TextureDimension dimension; + uint8_t baseArrayLayer; + uint8_t layerCount; + uint8_t baseMipLevel; + uint8_t levelCount; }; - struct TextureDesc { - ImagePtr image; - uint32_t width; - uint32_t height; - uint32_t depth : 16; - TinyImageFormat format : 16; - ResourceState state : 8; - SampleCount sampleCount : 8; - uint32_t arraySize : 8; - TextureDimension dimension : 4; - uint32_t mipLevel : 4; - TextureViewDesc ToTextureView() const{ - TextureViewDesc desc{}; + struct TextureKey { + uint32_t id; + uint16_t width; + uint16_t height; + uint16_t depth; + TinyImageFormat format; + SampleCount sampleCount; + TextureDimension dimension; + uint8_t mipLevel; + uint8_t arraySize; + }; + struct TextureDesc : TextureKey { + ImagePtr image; + void* pData;//api数据 比如 vulkan 包含了内存信息,删除图像时要用到 + ResourceState state; + TextureUsage usage;//这个字段是包含关系,即使不同,也可以指向相同的图像 + TextureViewKey ToTextureView() const{ + TextureViewKey desc{}; desc.image = image; desc.format = format; desc.baseArrayLayer = 0; @@ -222,39 +240,12 @@ namespace api { TextureBarrier ToBarrier(ResourceState from, ResourceState to)const; }; struct AttachmentDesc { - ImagePtr image; + TextureDesc texture; ImageViewPtr imageView; - uint32_t width; - uint32_t height; - TextureDimension dimension : 16; - TinyImageFormat colorFormat : 16; - SampleCount sampleCount : 16; - AttachmentDesc& FromTexture(const TextureDesc& desc) { - width = desc.width; - height = desc.height; - image = desc.image; - sampleCount = desc.sampleCount; - colorFormat = desc.format; - dimension = desc.dimension; - return *this; - } - TextureDesc ToTexture() const { - return TextureDesc{ - .image = image, - .width = width, - .height = height, - }; - } - TextureViewDesc ToTextureView() const { - TextureViewDesc desc{}; - desc.image = image; - desc.format = colorFormat; - desc.baseArrayLayer = 0; - desc.baseMipLevel = 0; - desc.layerCount = 1; - desc.levelCount = 1; - desc.dimension = dimension; - return desc; + AttachmentDesc() :texture(), imageView(nullptr) {}; + AttachmentDesc(const TextureDesc& desc): texture(desc), imageView(nullptr){} + TextureViewKey ToTextureView() const { + return texture.ToTextureView(); } TextureBarrier ToBarrier(ResourceState from, ResourceState to)const; }; @@ -309,10 +300,10 @@ namespace api { TextureBarrier barrier{}; barrier.mSrcState = from; barrier.mDstState = to; - barrier.mTexture = ToTexture(); + barrier.mTexture = texture; return barrier; } - inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) { + inline bool operator==(const TextureViewKey& k1, const TextureViewKey& k2) { if (k1.image != k2.image) return false; if (k1.format != k2.format) return false; if (k1.dimension != k2.dimension) return false; @@ -322,11 +313,9 @@ namespace api { 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; + inline bool operator==(const TextureKey& k1, const TextureKey& k2) { 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; @@ -339,17 +328,17 @@ namespace api { #include "meta/hash.h" namespace std { template<> - struct hash + struct hash { - size_t operator()(const api::TextureViewDesc& key) const noexcept + size_t operator()(const api::TextureViewKey& key) const noexcept { return meta::MurmurHashFn(key); } }; template<> - struct hash + struct hash { - size_t operator()(const api::TextureDesc& key) const noexcept + size_t operator()(const api::TextureKey& key) const noexcept { return meta::MurmurHashFn(key); } diff --git a/engine/modules/engine/render/src/graph/frame_graph.cpp b/engine/modules/engine/render/src/graph/frame_graph.cpp index 08cdcba..7838d8b 100644 --- a/engine/modules/engine/render/src/graph/frame_graph.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph.cpp @@ -4,26 +4,32 @@ #include #include namespace api { + //先准备再执行,这样就可以在执行之前,做一些特殊的资源初始化工作 FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor) { - FrameGraphNodePtr node_ptr{executor }; - RenderPassBuilder builder{ this, node_ptr }; - setup(*this, builder); + FrameGraphNodePtr node_ptr{ setup, executor}; mNodes.push_back(node_ptr); return node_ptr; } - FrameGraph::TextureBuilder FrameGraph::CreateTextureBuild() + RenderPassBuilder FrameGraph::CreateRenderPassBuild() { - return TextureBuilder{this}; + return RenderPassBuilder{this}; } - void FrameGraph::InitSurface(span surfaces) + void FrameGraph::InitSurface(TextureDesc* surfaces, uint32_t frames) { - mSurface = surfaces[0]; - RenderAPI* API = RenderAPI::Ptr(); - for (auto& surface : surfaces) { - TextureViewDesc desc = surface.ToTextureView(); - //ImageViewPtr view = API->CreateTextureView(desc); - //mResourceViewPool.emplace(desc, view); + mTexturePool.reserve(frames); + for (uint32_t i = 0; i < frames;i++) { + surfaces[i].id = mTexturePool.size() + 1; + mTexturePool.push_back(surfaces[i]); + } + } + void FrameGraph::Setup() + { + uint32_t size = mNodes.size(); + for (uint32_t i = 0; i < size;i++) { + auto& node = mNodes[i];//mNodes 数量可能会增加 + RenderPassBuilder builder{this, node}; + node->setup(*this, builder); } } void FrameGraph::Compile() @@ -42,6 +48,12 @@ namespace api { if ((!mLastOutputNode || node->type > mLastOutputNode->type)) { mLastOutputNode = node.node; } + if ((!mFirstInputNode || node->type < mFirstInputNode->type)) { +#ifdef WITH_EDITOR + if(!mIsRenderEditorSurface || node->type >= RenderPassNodeType::Imgui) +#endif // WITH_EDITOR + mFirstInputNode = node.node; + } } } while (!stack.empty()) { @@ -51,15 +63,10 @@ namespace api { continue; } node->isActive = true; - bool isInput = node->IsOutput(); for (auto& edge : node->inEdges) { - if (!edge->source->isActive) { - stack.push(edge.SourceNode()); + if (edge->node && !edge->node->isActive) { + stack.push(edge->node); } - 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) { @@ -86,8 +93,8 @@ namespace api { seenNodes.insert(node->dependencies[0]); } for (auto& edge : node->inEdges) { - RenderPassNode* srcNode = edge.SourceNode(); - if (seenNodes.insert(srcNode).second) { + RenderPassNode* srcNode = edge->node; + if (srcNode && seenNodes.insert(srcNode).second) { node->dependencies.push_back(srcNode); } } @@ -134,18 +141,25 @@ namespace api { } void FrameGraph::ExecutePresentPass(FRenderView& view) { - if (mSurface.state == ResourceState::PRESENT) { +#ifdef WITH_EDITOR + TextureDesc& surface = ResolveTexture(mIsRenderEditorSurface ? mEditorSurface : mSurface); +#else + TextureDesc& surface = ResolveTexture(mSurface); +#endif // WITH_EDITOR + if (surface.state == ResourceState::PRESENT) { + surface.state = ResourceState::UNDEFINED; return; } TextureBarrier barrier{}; - barrier.mSrcState = mSurface.state; + barrier.mSrcState = surface.state; barrier.mDstState = ResourceState::PRESENT; - barrier.mTexture = mSurface; + barrier.mTexture = surface; ResourceBarrierDesc desc{}; desc.type = RenderPassType::Present; desc.textureBarriersCount = 1; desc.pTextureBarriers = &barrier; view.context->ExecuteSurfaceBarriers(desc); + surface.state = ResourceState::UNDEFINED; } void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view) { @@ -162,12 +176,11 @@ namespace api { pmr::vector bufferBarrier{FramePool()}; pmr::vector textureBarrier{ FramePool() }; auto graph = &RenderAPI::Ptr()->graph; - node->ForeachEdge([&](FrameResource* resource, FrameGraphEdgePtr edge) { + node->ForeachEdge([&](FrameResource* resource) { std::visit([&](auto& desc) { - ResourceState targetState = edge.targetState; - ResourceState sourceState = graph->Resolve(resource->name, desc, targetState); - if (sourceState != targetState) { - auto barrier = desc.ToBarrier(sourceState, targetState); + ResourceState srcstate, dststate; + if (!graph->ResolveState(desc, srcstate, dststate)) { + auto barrier = desc.ToBarrier(srcstate, dststate); using T = decltype(barrier); if constexpr (std::is_same_v) { bufferBarrier.push_back(barrier); @@ -176,7 +189,7 @@ namespace api { textureBarrier.push_back(barrier); } } - }, resource->resource); + }, resource->res); }); if (bufferBarrier.empty() && textureBarrier.empty()) { return; @@ -189,47 +202,104 @@ namespace api { desc.pTextureBarriers = textureBarrier.data(); RenderAPI::Ptr()->ExecuteResourceBarriers(desc); } - ResourceState FrameGraph::Resolve(Name name, TextureDesc& desc, ResourceState state) + void FrameGraph::TransitionState(TextureDesc& desc, ResourceState state) { - ResourceState sourceState = ResourceState::UNDEFINED; - if (name == NameSurface) { - mSurface = desc; - } - return sourceState; - } - ResourceState FrameGraph::Resolve(Name name, AttachmentDesc& desc, ResourceState state) - { - ResourceState sourceState = ResourceState::UNDEFINED; - if (name == NameSurface) { - sourceState = mSurface.state; + TextureDesc& texture = ResolveTexture(desc); + desc.state = state; + texture.state = state; + if (texture.id == mSurface.id) { mSurface.state = state; - return sourceState; } - return sourceState; - } - ResourceState FrameGraph::Resolve(Name name, BufferDesc& desc, ResourceState state) - { - ResourceState sourceState = ResourceState::UNDEFINED; - return sourceState; - } - ImagePtr FrameGraph::ResolveTexture(TextureDesc desc) - { - auto it = mTexturePool.find(desc); - if (it != mTexturePool.end()) { - return it->second; +#ifdef WITH_EDITOR + else if (texture.id == mEditorSurface.id) { + mEditorSurface.state = state; } - ImagePtr image = RenderAPI::Ptr()->CreateTexture(desc); - mTexturePool.emplace(desc, image); - return image; +#endif // WITH_EDITOR } - ImageViewPtr FrameGraph::ResolveTextureView(TextureViewDesc desc) + bool FrameGraph::ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate) { - auto it = mTextureViewPool.find(desc); + TextureDesc& texture = ResolveTexture(desc); + srcstart = texture.state; + dststate = desc.state; + texture.state = dststate; + if (texture.id == mSurface.id) { + mSurface.state = dststate; + } +#ifdef WITH_EDITOR + else if (texture.id == mEditorSurface.id) { + mEditorSurface.state = dststate; + } +#endif // WITH_EDITOR + return srcstart == dststate; + } + bool FrameGraph::ResolveState(AttachmentDesc& desc, ResourceState& srcstart, ResourceState& dststate) + { + return ResolveState(desc.texture, srcstart, dststate); + } + bool FrameGraph::ResolveState(BufferDesc& desc, ResourceState& srcstart, ResourceState& dststate) + { + return true; + } + TextureDesc& FrameGraph::ResolveTexture(TextureDesc& desc) + { + if (!desc.id || desc.id > mTexturePool.size()) { + return desc; + } + TextureDesc& texture = mTexturePool[desc.id - 1]; + if (!texture.image) { + RenderAPI::Ptr()->CreateTexture(texture); + } + return texture; + } + ImageViewPtr FrameGraph::ResolveTextureView(TextureDesc& desc) + { + if (!desc.image) { + desc = ResolveTexture(desc); + } + return ResolveTextureView(desc.ToTextureView()); + } + ImageViewPtr FrameGraph::ResolveTextureView(TextureViewKey key) + { + auto it = mTextureViewPool.find(key); if (it != mTextureViewPool.end()) { return it->second; } - ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(desc); - mTextureViewPool.emplace(desc, view); + ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(key); + mTextureViewPool.emplace(key, view); return view; } + TextureDesc FrameGraph::ResourceTexture(Name name, int num) + { + Tag tag(name, num); + auto it = mTextureTagMap.find(tag); + if (it != mTextureTagMap.end()) { + return it->second; + } + return TextureDesc{}; + } + void FrameGraph::ResourceTexture(TextureDesc& desc) + { + auto it = mTextureKeyMap.find(desc); + if (it != mTextureKeyMap.end()) { + desc.id = it->second; + } + else { + desc.id = mTexturePool.size() + 1; + mTextureKeyMap[desc] = desc.id; + mTexturePool.push_back(desc); + } + } + void FrameGraph::SetResourceTexture(TextureDesc desc, Name name, int num) + { + if (!desc.id) { + desc.id = mTexturePool.size() + 1; + mTexturePool.push_back(desc); + } + Tag tag(name, num); + //auto it = mTextureTagMap.find(tag); + //if (it != mTextureTagMap.end()) { + //todo: destroy texture + //} + mTextureTagMap[tag] = desc; + } } 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 194b2f5..dcb640f 100644 --- a/engine/modules/engine/render/src/graph/frame_graph_builder.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph_builder.cpp @@ -1,70 +1,24 @@ #include "render/graph/frame_graph.h" #include "render/pass/render_pass.h" namespace api { - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name) + RenderPassBuilder& RenderPassBuilder::Name(pmr::Name name) { node->name = name; return *this; } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Type(RenderPassNodeType type, RenderPassNodeFlag flag) + RenderPassBuilder& RenderPassBuilder::Type(RenderPassNodeType type, RenderPassNodeFlag flag) { node->type = type; node->flag = flag; return *this; } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state) - { - FrameGraphEdgePtr edge{}; - edge.targetState = state; - resource = edge.Make(); - resource->source = node; - resource->resource = desc; - node->inEdges.push_back(edge); - return *this; - } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(BufferDesc desc, ResourceState state) + RenderPassBuilder& RenderPassBuilder::Write(AttachmentDesc desc, ResourceState state, pmr::Name name) { - FrameGraphEdgePtr edge{}; - edge.targetState = state; - resource = edge.Make(); - resource->source = node; - resource->resource = desc; + desc.texture.state = state; + FrameGraphEdgePtr edge = FrameResource::Make(name, desc, node.node); node->outEdges.push_back(edge); return *this; } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc, ResourceState state) - { - FrameGraphEdgePtr edge{}; - edge.targetState = state; - resource = edge.Make(); - resource->source = node; - resource->resource = desc; - node->outEdges.push_back(edge); - return *this; - } - - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& refEdge, ResourceState state) - { - if (!refEdge) { return *this; } - FrameGraphEdgePtr edge{ refEdge , state}; - node->inEdges.emplace_back(edge); - refEdge->targets.emplace_back(node); - return *this; - } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state) - { - if (!refEdge) { return *this; } - FrameGraphEdgePtr edge{ refEdge , state }; - node->outEdges.emplace_back(edge); - refEdge->targets.emplace_back(node); - return *this; - } - FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc) - { - edge->name = name; - edge->resource = desc; - return *this; - } } \ No newline at end of file diff --git a/engine/modules/engine/render/src/graph/type.cpp b/engine/modules/engine/render/src/graph/type.cpp index 0da64c1..ee2ae1a 100644 --- a/engine/modules/engine/render/src/graph/type.cpp +++ b/engine/modules/engine/render/src/graph/type.cpp @@ -1,20 +1,18 @@ #include "render/graph/type.h" #include "render/renderapi.h" namespace api { - void FrameGraphEdgePtr::ResolveView(FrameGraph* graph) - { - if (resource->IsAttachment()) { - AttachmentDesc& attach = resource->CastTo(); - TextureViewDesc desc = attach.ToTextureView(); - attach.imageView = graph->ResolveTextureView(desc); - } - } void RenderPassNode::ForeachEdge(RenderPassEdgeIterFn fn) { for (auto& edge : inEdges) { - fn(edge.resource, edge); + fn(edge); } for (auto& edge : outEdges) { - fn(edge.resource, edge); + fn(edge); } } + FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor, NodeType type) : type(type) + { + node = new (FramePool()) RenderPassNode(); + node->setup = setup; + node->executor = executor; + } } diff --git a/engine/modules/engine/render/src/pass/demo_pass.cpp b/engine/modules/engine/render/src/pass/demo_pass.cpp index f6aca5f..53484c3 100644 --- a/engine/modules/engine/render/src/pass/demo_pass.cpp +++ b/engine/modules/engine/render/src/pass/demo_pass.cpp @@ -9,16 +9,12 @@ namespace api { static RscHandle material; static RscHandle shader; static RscHandle mesh; - void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) + void DemoPass::Setup(FrameGraph& graph, RenderPassBuilder& builder) { - AttachmentDesc surface{}; - surface.FromTexture(graph.mSurface); - auto edge = graph.CreateTextureBuild() - .Import(FrameGraph::NameSurface, surface) - .Edge(); + AttachmentDesc surface{ graph.mSurface }; builder.Name("MiniPass") .Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Output) - .Write(edge, ResourceState::COLOR_ATTACHMENT); + .Write(surface, ResourceState::COLOR_ATTACHMENT); } void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx) { diff --git a/engine/modules/engine/zlib/include/pmr/name.h b/engine/modules/engine/zlib/include/pmr/name.h index e317754..85fb623 100644 --- a/engine/modules/engine/zlib/include/pmr/name.h +++ b/engine/modules/engine/zlib/include/pmr/name.h @@ -173,17 +173,15 @@ namespace pmr { UNIQUER_INLINE_STATIC(StringEntryMemoryManager, stringEntryMemoryManager, "pmr::name::stringEntryMemoryManager") uint32_t flag3_memory29; public: + friend class std::hash; Name()noexcept : flag3_memory29(0) {}; Name(std::string view) noexcept : flag3_memory29(MakeInterned(view)) {}; Name(std::string_view view) noexcept : flag3_memory29(MakeInterned(view)) {}; template Name(const char(&str)[N]) noexcept : Name(std::string_view(str)) {} Name(const char* str)noexcept : Name(std::string_view(str)){}; - auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; }; + constexpr auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; }; uint32_t MakeInterned(std::string_view view); - uint32_t Hash() const{ - return flag3_memory29; - } operator uint32_t() const { return flag3_memory29; } @@ -212,14 +210,38 @@ namespace pmr { return std::string(stringEntry->GetData(), stringEntry->GetSize()); } }; + + class Tag { + private: + Name name; + int number; + public: + friend class std::hash; + Tag(Name name, int number): name(name), number(number) {} + Tag(Name name): name(name), number(0) {} + Tag(): name(), number(0) {} + Name getName() const { return name; } + int getNumber() const { return number; } + constexpr auto operator<=>(const Tag& other) const noexcept = default; + }; } namespace std { template<> struct hash<::pmr::Name> { - uint32_t operator()(const ::pmr::Name& name) const noexcept + size_t operator()(const ::pmr::Name& name) const noexcept { - return name.Hash(); + return std::hash{}(name.flag3_memory29); + } + }; + template<> + struct hash<::pmr::Tag> + { + size_t operator()(const ::pmr::Tag& tag) const noexcept + { + size_t h1 = std::hash{}((uint32_t)tag.name); + size_t h2 = std::hash{}(tag.number); + return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); } }; } diff --git a/engine/modules/render/vulkan/include/vkn/thread/buffer_worker.h b/engine/modules/render/vulkan/include/vkn/thread/buffer_worker.h index e8d8b26..ddb6937 100644 --- a/engine/modules/render/vulkan/include/vkn/thread/buffer_worker.h +++ b/engine/modules/render/vulkan/include/vkn/thread/buffer_worker.h @@ -37,6 +37,10 @@ namespace vkn { BufferCommand(const BufferUpload& cmd) : cmd(cmd){} BufferCommand(const BufferCreator& cmd) : cmd(cmd) {} }; + struct ImageCreator { + VkImageCreateInfo imageInfo; + VkImage* image; + }; class BufferWorker : public ThreadWorker{ public: //pmr::vector mPool{BufferPool()}; @@ -45,5 +49,6 @@ namespace vkn { void Loop(); void UploadBuffer(const BufferUpload& elem); void CreateBuffer(BufferCreator& elem); + void CreateImage(ImageCreator& elem); }; }; diff --git a/engine/modules/render/vulkan/include/vkn/type.h b/engine/modules/render/vulkan/include/vkn/type.h index bcf1037..fef5844 100644 --- a/engine/modules/render/vulkan/include/vkn/type.h +++ b/engine/modules/render/vulkan/include/vkn/type.h @@ -18,7 +18,7 @@ namespace vkn { using commandFn = std::function; using api::TargetBufferFlags; using api::ResourceBarrierDesc; - using api::TextureViewDesc; + using api::TextureViewKey; using api::ImageViewPtr; using api::ImagePtr; using api::TextureDimension; diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api.h b/engine/modules/render/vulkan/include/vkn/vulkan_api.h index 33d6241..c5bee95 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api.h @@ -15,10 +15,10 @@ namespace vkn { private: VulkanWindow& window; Backend backend; - table MeshTable; - table PipelineTable; - table RenderPassCache; - table RenderPassNameCache; + table MeshTable; + table PipelineTable; + table RenderPassCache; + table RenderPassNameCache; table FramebufferCache; public: VulkanAPI(); @@ -32,8 +32,8 @@ namespace vkn { void LoadShader(Shader& shader, size_t passKey)override; void CreateBuffer(BufferDesc& desc) override; - ImagePtr CreateTexture(TextureDesc desc)override; - ImageViewPtr CreateTextureView(TextureViewDesc desc)override; + void CreateTexture(TextureDesc& desc)override; + ImageViewPtr CreateTextureView(TextureViewKey desc)override; void BeginFrame()override; void EndFrame()override; diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h b/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h index 1aeb24a..b0cc76f 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h @@ -1,5 +1,6 @@ #include "type.h" namespace vkn { + using api::TextureUsage; using api::ResourceState; using api::TextureBarrier; using api::ShaderDescriptorType; @@ -16,7 +17,7 @@ namespace vkn { VkImageLayout vkApiGetImageLayout(ResourceState layout); VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier); VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit); - VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState); + VkImageUsageFlags vkApiGetImageUsageFlags(TextureUsage usage); VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize); VkImageType vkApiGetImageType(TextureDimension dimension); VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize); diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_imgui_editor.h b/engine/modules/render/vulkan/include/vkn/vulkan_imgui_editor.h index bddc231..3e71836 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_imgui_editor.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_imgui_editor.h @@ -2,18 +2,24 @@ #include "render/editor_system.h" #include "render/graph/frame_graph.h" namespace vkn { + using api::TextureDesc; using api::FrameGraph; using api::RenderPassContext; + using api::RenderPassBuilder; + using api::RenderEditorContext; class VulkanImguiEditor : public api::EditorSystem { public: void Initialize() override; void Finalize() override; - void Render(); - void OnBeginRenderFrame(); + + ImTextureID AddTexture(const TextureDesc& desc) override; + + void Render(FrameGraph& graph, RenderEditorContext& ctx); + void OnBeginRenderFrame(FrameGraph& graph, uint32_t frame); static VulkanImguiEditor* Ptr() { return (VulkanImguiEditor*)api::EditorSystem::Ptr(); }; - static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder); + static void Setup(FrameGraph& graph, RenderPassBuilder& builder); static void Execute(FrameGraph&, RenderPassContext&); }; } \ No newline at end of file diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_window.h b/engine/modules/render/vulkan/include/vkn/vulkan_window.h index 9c42bfe..4933826 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_window.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_window.h @@ -32,12 +32,6 @@ namespace vkn { VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); void Aquire(VulkanContext& ctx); void Present(VulkanContext& ctx); - int FrameCount() const { - return mFrames; - } - const pmr::vector& GetSurface() { - return mSurfaces; - } }; class VULKAN_API VulkanWindow : public api::Window { private: diff --git a/engine/modules/render/vulkan/src/thread/buffer_worker.cpp b/engine/modules/render/vulkan/src/thread/buffer_worker.cpp index f5d1844..0938b3e 100644 --- a/engine/modules/render/vulkan/src/thread/buffer_worker.cpp +++ b/engine/modules/render/vulkan/src/thread/buffer_worker.cpp @@ -90,4 +90,13 @@ namespace vkn { if (elem.ppCpuData) vmaMapMemory(vmaAllocator, *elem.pAllocation, elem.ppCpuData); } + void BufferWorker::CreateImage(ImageCreator& elem) + { + // 创建图像并分配内存 + VmaAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; + + VmaAllocation allocation; + VkResult result = vmaCreateImage(vmaAllocator, &elem.imageInfo, &allocCreateInfo, elem.image, &allocation, nullptr); + } } diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index f672d62..232c3f5 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -269,12 +269,8 @@ namespace vkn { { } - ImagePtr VulkanAPI::CreateTexture(TextureDesc desc) + void VulkanAPI::CreateTexture(TextureDesc& desc) { - if (desc.image) { - return desc.image; - } - uint32_t depth = any(desc.dimension & TextureDimension::TEX_3D) ? 3 : 1; VkImageCreateInfo imageCreateInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = NULL, @@ -290,15 +286,16 @@ namespace vkn { .arrayLayers = desc.arraySize, .samples = vkApiGetSmpleCountFlag(desc.sampleCount), .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = vkApiGetImageUsageFlags(desc.state), + .usage = vkApiGetImageUsageFlags(desc.usage), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = NULL, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED + .initialLayout = vkApiGetImageLayout(desc.state) }; - return ImagePtr(); + ImageCreator imageCreator{ .imageInfo = imageCreateInfo ,.image = (VkImage*)&desc.image }; + Backend::TransferWorker->CreateImage(imageCreator); } - ImageViewPtr VulkanAPI::CreateTextureView(TextureViewDesc desc) + ImageViewPtr VulkanAPI::CreateTextureView(TextureViewKey desc) { VkImageViewCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -332,8 +329,8 @@ namespace vkn { { VulkanContext& ctx = *(VulkanContext*)&context; window.Aquire(ctx); - graph.mSurface = ctx.surface; - EventSystem::Ptr()->BeginRenderFrame.Invoke(); + graph.Input(ctx.surface); + EventSystem::Ptr()->BeginRenderFrame.Invoke(graph, ctx.frame); } void VulkanAPI::EndFrame() { @@ -361,7 +358,6 @@ namespace vkn { } void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) { - RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash); RenderPassKey config{}; FramebufferKey frameKey{.layers = 1}; VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 }; @@ -369,22 +365,24 @@ namespace vkn { for (auto& it : node->outEdges) { if (it->IsAttachment()) { auto& desc = it->CastTo(); - - config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat); - config.samples = vkApiGetSmpleCountFlag(desc.sampleCount); + TextureDesc& texture = desc.texture; + config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(texture.format); + config.samples = vkApiGetSmpleCountFlag(texture.sampleCount); TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i); config.clear |= flag; - it.ResolveView(&graph); + desc.imageView = graph.ResolveTextureView(texture); + frameKey.imageViews[i] = (VkImageView)desc.imageView; - frameKey.height = desc.height; - frameKey.width = desc.width; + frameKey.height = texture.height; + frameKey.width = texture.width; //clearValues[i] = i++; } } frameKey.attachmentCount = i; + RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash); if (!passInfo) { passInfo = GetRenderPassInfo(node->hash, config); } diff --git a/engine/modules/render/vulkan/src/vulkan_api_help.cpp b/engine/modules/render/vulkan/src/vulkan_api_help.cpp index bbfcb57..c2cdd10 100644 --- a/engine/modules/render/vulkan/src/vulkan_api_help.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api_help.cpp @@ -179,12 +179,12 @@ namespace vkn { } return result; } - VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState) + VkImageUsageFlags vkApiGetImageUsageFlags(TextureUsage usage) { VkImageUsageFlags usageFlags = 0; - if (any(startState & ResourceState::COLOR_ATTACHMENT)) + if (any(usage & TextureUsage::COLOR_ATTACHMENT)) usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - else if (any(startState & ResourceState::DEPTH_ATTACHMENT)) + else if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; return usageFlags; } @@ -223,7 +223,7 @@ namespace vkn { if (any(dimension & TextureDimension::TEX_CUBE)) { flag |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; } - if (arraySize > 0) { + if (arraySize > 1) { flag |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR; } return flag; diff --git a/engine/modules/render/vulkan/src/vulkan_imgui_editor.cpp b/engine/modules/render/vulkan/src/vulkan_imgui_editor.cpp index 432397a..a7154aa 100644 --- a/engine/modules/render/vulkan/src/vulkan_imgui_editor.cpp +++ b/engine/modules/render/vulkan/src/vulkan_imgui_editor.cpp @@ -8,6 +8,7 @@ #include "vkn/wrapper/queue.h" #include "imgui/imgui_impl_vulkan.h" #include "imgui/imgui_impl_sdl2.h" +#include "data/global.h" #include "event/event_system.h" #include "tinyimageformat/tinyimageformat_apis.h" namespace vkn { @@ -88,7 +89,7 @@ namespace vkn { Backend& backend = API->GetBackend(); Queue* pQueue = backend.GetDevice().GetQueue(Queue::RenderQueue); VkDescriptorPool descriptorPool = CreateDescriptorPool(backend.GetDevice().Ptr()); - VkRenderPass renderPass = CreateRenderPass(API->graph.mSurface.format, backend.GetDevice().Ptr()); + VkRenderPass renderPass = CreateRenderPass(API->context.surface.format, backend.GetDevice().Ptr()); ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = backend.GetInstance().Ptr(); @@ -98,7 +99,7 @@ namespace vkn { init_info.Queue = pQueue->Ptr(); init_info.DescriptorPool = descriptorPool; init_info.MinImageCount = 2; - init_info.ImageCount = window->Swapchain()->FrameCount(); + init_info.ImageCount = API->context.frameCount; init_info.RenderPass = renderPass; init_info.PipelineCache = VK_NULL_HANDLE; init_info.Subpass = 0; @@ -106,42 +107,69 @@ namespace vkn { init_info.Allocator = VK_NULL_HANDLE; ImGui_ImplVulkan_Init(&init_info); API->SetRenderPassInfo(ImguiPassName, renderPass); + //gEngineConfig.IsRenderEditorSurface = true; + if (gEngineConfig.IsRenderEditorSurface) { + TextureDesc desc{}; + desc.width = 200; + desc.height = 200; + desc.format = TinyImageFormat_FromVkFormat((TinyImageFormat_VkFormat)VK_FORMAT_B8G8R8A8_SRGB); + desc.state = ResourceState::UNDEFINED; + desc.sampleCount = SampleCount::SAMPLE_COUNT_1; + desc.arraySize = 1; + desc.mipLevel = 1; + desc.depth = 1; + desc.dimension = TextureDimension::TEX_2D; + desc.usage = TextureUsage::COLOR_ATTACHMENT; + for (uint32_t i = 0; i < API->context.frameCount; i++) { + API->graph.SetResourceTexture(desc, FrameGraph::NameEditorSurface, i); + } + } EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiEditor::OnBeginRenderFrame, this); } void VulkanImguiEditor::Finalize() { } - void VulkanImguiEditor::Render() + ImTextureID VulkanImguiEditor::AddTexture(const TextureDesc& desc) + { + // 2. 通过 ImGui_ImplVulkan_AddTexture 连接 Vulkan 纹理和 ImGui + //ImTextureID textureID = (ImTextureID)(intptr_t)textureImageView; + //ImGui_ImplVulkan_AddTexture(textureSampler, textureImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + return ImTextureID{}; + } + void VulkanImguiEditor::Render(FrameGraph& graph, RenderEditorContext& ctx) { for (auto win : mWindows) { - win->Draw(); + win->Draw(graph, ctx); } } - void VulkanImguiEditor::OnBeginRenderFrame() + void VulkanImguiEditor::OnBeginRenderFrame(FrameGraph& graph, uint32_t frame) { - VulkanAPI::Ptr()->graph.AddRenderPass(); + graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface; + if (gEngineConfig.IsRenderEditorSurface) { + graph.mEditorSurface = graph.mSurface; + graph.mSurface = graph.ResourceTexture(FrameGraph::NameEditorSurface, frame); + } + graph.AddRenderPass(); } - void VulkanImguiEditor::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) + void VulkanImguiEditor::Setup(FrameGraph& graph, RenderPassBuilder& builder) { - AttachmentDesc surface{}; - surface.FromTexture(graph.mSurface); - auto edge = graph.CreateTextureBuild() - .Import(FrameGraph::NameSurface, surface) - .Edge(); + AttachmentDesc surface{ gEngineConfig.IsRenderEditorSurface ? graph.mEditorSurface : graph.mSurface }; builder.Name(ImguiPassName) .Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output) - .Write(edge, ResourceState::COLOR_ATTACHMENT); + .Write(surface, ResourceState::COLOR_ATTACHMENT); } void VulkanImguiEditor::Execute(FrameGraph& graph, RenderPassContext& context) { - graph.mSurface.state = ResourceState::PRESENT; + TextureDesc& surface = graph.mEditorSurface.image ? graph.mEditorSurface : graph.mSurface; + graph.TransitionState(surface, ResourceState::PRESENT); ImGui_ImplVulkan_NewFrame(); ImGui_ImplSDL2_NewFrame(); ImGui::NewFrame(); - VulkanImguiEditor::Ptr()->Render(); + RenderEditorContext editorContext{}; + VulkanImguiEditor::Ptr()->Render(graph, editorContext); ImGui::Render(); VulkanContext& ctx = *(VulkanContext*)context.parent; diff --git a/engine/modules/render/vulkan/src/vulkan_window.cpp b/engine/modules/render/vulkan/src/vulkan_window.cpp index fa6ce2d..9a1c17e 100644 --- a/engine/modules/render/vulkan/src/vulkan_window.cpp +++ b/engine/modules/render/vulkan/src/vulkan_window.cpp @@ -23,7 +23,8 @@ namespace vkn { args.height = mHeight; mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args); api->context.frameCount = args.frames; - api->graph.InitSurface(std::span{mSwapchain->mSurfaces.data(), args.frames}); + api->context.surface = mSwapchain->mSurfaces[0]; + api->graph.InitSurface(mSwapchain->mSurfaces.data(), mSwapchain->mSurfaces.size()); return true; } VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args) diff --git a/engine/src/editor/panel/asset_preview_panel.cpp b/engine/src/editor/panel/asset_preview_panel.cpp index 0b9a1db..ae9ff4c 100644 --- a/engine/src/editor/panel/asset_preview_panel.cpp +++ b/engine/src/editor/panel/asset_preview_panel.cpp @@ -1,9 +1,17 @@ #include "editor/panel/asset_preview_panel.h" +#include "data/global.h" #include namespace api { - void AssetPreviewPanel::DrawPanel() { + void AssetPreviewPanel::DrawPanel(FrameGraph& graph, RenderEditorContext& context) { static float my_float = 0.5f; ImGui::Text("This is some useful text."); ImGui::SliderFloat("float", &my_float, 0.0f, 1.0f); + if (gEngineConfig.IsRenderEditorSurface) { + TextureDesc& surface = graph.mSurface; + // 2. 通过 ImGui_ImplVulkan_AddTexture 连接 Vulkan 纹理和 ImGui + //ImTextureID textureID = (ImTextureID)(intptr_t)graph.ResolveTextureView(surface); + // 3. 在 ImGui 窗口中渲染 Vulkan 纹理 + //ImGui::Image(textureID, ImVec2(surface.width, surface.height)); + } } } \ No newline at end of file diff --git a/engine/src/editor/panel/menu_bar_panel.cpp b/engine/src/editor/panel/menu_bar_panel.cpp index e8d7ed9..8023e34 100644 --- a/engine/src/editor/panel/menu_bar_panel.cpp +++ b/engine/src/editor/panel/menu_bar_panel.cpp @@ -2,7 +2,7 @@ #include namespace api { - void MenuBarPanel::DrawPanel() + void MenuBarPanel::DrawPanel(FrameGraph& graph, RenderEditorContext& context) { // 面板大小和位置 if (ImGui::BeginMenu("Tools")) { diff --git a/engine/src/editor/window/editor_main_window.cpp b/engine/src/editor/window/editor_main_window.cpp index 062849f..7821867 100644 --- a/engine/src/editor/window/editor_main_window.cpp +++ b/engine/src/editor/window/editor_main_window.cpp @@ -8,11 +8,11 @@ namespace api { AddPanel(); AddPanel(); } - void EditorMainWindow::Draw() + void EditorMainWindow::Draw(FrameGraph& graph, RenderEditorContext& context) { ImGui::Begin("MainWindow"); for (auto panel : mPanels) { - panel->DrawPanel(); + panel->DrawPanel(graph, context); } ImGui::End(); } diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index 03247fb..cf2d6a1 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -27,8 +27,8 @@ void ZWorldModule::OnLoad(int argc, char** argv) #ifdef WITH_EDITOR //绑定窗口交互 ImGui_ImplSDL2_InitForVulkan(window->GetPtr()); #endif - EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, []() { - API->graph.AddRenderPass(); + EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, [](FrameGraph& graph, uint32_t frame) { + graph.AddRenderPass(); }); } void ZWorldModule::Initialize()