From 9b1704246d0c7916fb7599fb5f380992aee7565c Mon Sep 17 00:00:00 2001 From: ouczbs Date: Mon, 21 Oct 2024 16:31:02 +0800 Subject: [PATCH] vulkan api bugfix --- .../modules/engine/core/3rdparty/singleton.h | 2 +- .../engine/render/impl/renderapi_impl.inl | 12 ++ .../render/include/render/graph/frame_graph.h | 16 +- ...raph_builder.h => frame_graph_builder.inl} | 10 +- .../engine/render/include/render/graph/type.h | 9 +- .../render/include/render/pass/demo_pass.h | 4 +- .../engine/render/include/render/renderapi.h | 10 +- .../engine/render/include/render/type.h | 137 +++++++++++----- .../engine/render/src/graph/frame_graph.cpp | 61 ++++++- .../render/src/graph/frame_graph_builder.cpp | 47 +++--- .../modules/engine/render/src/graph/type.cpp | 39 ++++- .../engine/render/src/pass/demo_pass.cpp | 12 +- engine/modules/engine/render/xmake.lua | 2 +- .../modules/render/vulkan/include/vkn/type.h | 25 ++- .../render/vulkan/include/vkn/vulkan_api.h | 6 +- .../vulkan/include/vkn/vulkan_api_help.h | 11 +- .../render/vulkan/include/vkn/vulkan_window.h | 7 +- .../modules/render/vulkan/src/vulkan_api.cpp | 147 +++++++++++++++-- .../render/vulkan/src/vulkan_api_help.cpp | 153 ++++++++++++++---- .../render/vulkan/src/vulkan_window.cpp | 14 +- game/zworld/src/zworld.cpp | 9 +- 21 files changed, 576 insertions(+), 157 deletions(-) rename engine/modules/engine/render/include/render/graph/{frame_graph_builder.h => frame_graph_builder.inl} (72%) diff --git a/engine/modules/engine/core/3rdparty/singleton.h b/engine/modules/engine/core/3rdparty/singleton.h index f3f2e12..f12444e 100644 --- a/engine/modules/engine/core/3rdparty/singleton.h +++ b/engine/modules/engine/core/3rdparty/singleton.h @@ -10,7 +10,7 @@ public: ~Singleton() { ms_Singleton = nullptr; } - static constexpr T* Ptr(void) { + static T* Ptr(void) { return ms_Singleton; } }; \ No newline at end of file diff --git a/engine/modules/engine/render/impl/renderapi_impl.inl b/engine/modules/engine/render/impl/renderapi_impl.inl index ab9ce17..b7ad8e0 100644 --- a/engine/modules/engine/render/impl/renderapi_impl.inl +++ b/engine/modules/engine/render/impl/renderapi_impl.inl @@ -1,6 +1,7 @@ #include "render/renderapi.h" #include "render/module.h" namespace api { + RenderAPI* API; IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render); void RenderAPI::RenderView(FRenderView& view) { @@ -15,4 +16,15 @@ namespace api { RenderView(view); } } + RenderAPI::RenderAPI(RenderContext* ctx) : context(*ctx) + { + API = this; + } + RenderAPI::~RenderAPI() + { + delete& context; + } + RenderAPI* RenderAPI::Ptr() { + return API; + } } \ 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 d12fa9c..2539142 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph.h @@ -10,15 +10,16 @@ namespace api { public: TextureDesc mSurface; table mResourceTable; - table mResourcePool; - table mResourceViewPool; + table mResourcePool; + table mResourceViewPool; lemon::ListGraph mGraph; pmr::vector mNodes{FramePool()}; public: template FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); } - using RenderPassSetupFunction = std::function; + using RenderPassSetupFunction = std::function; FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor); + FrameGraphNodePtr AddPresent(const FrameGraphEdgePtr& edge); using TextureSetupFunction = std::function; FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup); @@ -26,12 +27,18 @@ namespace api { void Execute(FRenderView& view); void Clear(); TextureDesc Resource(Name name) { + constexpr size_t surface = pmr::string_hash("surface"); + if (name.Hash() == surface) { + return mSurface; + } auto it = mResourceTable.find(name); if (it == mResourceTable.end()) { return {}; } return it->second; } + ImagePtr ResolveTexture(TextureDesc desc); + ImageViewPtr ResolveTextureView(TextureViewDesc desc); public: void ExecuteRenderPass(RenderPassNode* node, FRenderView& view); void ExecutePresentPass(RenderPassNode* node, FRenderView& view); @@ -40,4 +47,5 @@ namespace api { void ExecuteResourceBarriers(RenderPassNode* node); }; -} \ No newline at end of file +} +#include "frame_graph_builder.inl" \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/graph/frame_graph_builder.h b/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl similarity index 72% rename from engine/modules/engine/render/include/render/graph/frame_graph_builder.h rename to engine/modules/engine/render/include/render/graph/frame_graph_builder.inl index cdfc6a1..c093423 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph_builder.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph_builder.inl @@ -1,5 +1,4 @@ #pragma once -#include "frame_graph.h" namespace api { struct FrameGraph::RenderPassBuilder { FrameGraph& graph; @@ -9,19 +8,18 @@ namespace api { RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept : graph(*graph) , node(node) {}; FrameGraph::RenderPassBuilder& Name(pmr::Name name); - FrameGraph::RenderPassBuilder& Pass(RenderPass* pass); 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& edge); - FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& edge); + FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& refEdge, ResourceState state); + FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& refEdge, ResourceState state); + FrameGraph::RenderPassBuilder& Present(const FrameGraphEdgePtr& refEdge, ResourceState state); }; struct FrameGraph::TextureBuilder { FrameGraph& graph; FrameGraphEdgePtr& edge; public: TextureBuilder(FrameGraph* graph, FrameGraphEdgePtr& edge)noexcept : graph(*graph), edge(edge) {}; - FrameGraph::TextureBuilder& Name(pmr::Name name); - FrameGraph::TextureBuilder& Import(ImagePtr& ptr, AttachmentDesc desc, ResourceState state); + FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc, ResourceState state); }; } \ 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 64d08c6..bfb5b8f 100644 --- a/engine/modules/engine/render/include/render/graph/type.h +++ b/engine/modules/engine/render/include/render/graph/type.h @@ -27,6 +27,7 @@ namespace api { NodeType type{ NodeType::Render }; RenderPassNode* node; FrameGraphNodePtr() : node(nullptr){}; + FrameGraphNodePtr(GraphNodeRef ref, NodeType type = NodeType::Present); FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); operator bool() const { return node; @@ -34,6 +35,7 @@ namespace api { RenderPassNode* operator ->()const { return node; } + void Presnet(FrameGraph&, RenderPassContext&); }; struct FrameResource { using Resource = std::variant; @@ -59,8 +61,11 @@ namespace api { struct FrameGraphEdgePtr { ResourceState targetState; FrameResource* resource; - ImagePtr* ppImage; FrameGraphEdgePtr() = default; + FrameGraphEdgePtr(const FrameGraphEdgePtr& edge, ResourceState state) { + targetState = state; + resource = edge.resource; + } FrameResource* Make() { resource = new (FramePool()) FrameResource(); return resource; @@ -72,11 +77,11 @@ namespace api { return resource; } void Resolve(FrameGraph* graph); + void ResolveView(FrameGraph* graph); }; using RenderPassEdgeIterFn = std::function; struct RenderPassNode { Name name; - const void* pass; RenderPassNodeExecuteFn executor; pmr::vector inEdges{ FramePool() }; pmr::vector outEdges{ FramePool() }; 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 8a4de5e..755ce98 100644 --- a/engine/modules/engine/render/include/render/pass/demo_pass.h +++ b/engine/modules/engine/render/include/render/pass/demo_pass.h @@ -1,10 +1,10 @@ #pragma once #include "render_pass.h" -#include "render/graph/frame_graph_builder.h" +#include "render/graph/frame_graph.h" namespace api { class DemoPass : public RenderPass { public: - static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder); + static bool Setup(FrameGraph& graph, FrameGraph::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 77197d1..37482f5 100644 --- a/engine/modules/engine/render/include/render/renderapi.h +++ b/engine/modules/engine/render/include/render/renderapi.h @@ -7,19 +7,21 @@ namespace api { class Mesh; class Shader; class RenderPassNode; - class RENDER_API RenderAPI : public Singleton + class RENDER_API RenderAPI { public: RenderContext& context; FrameGraph graph; - RenderAPI(RenderContext* ctx) : context(*ctx){}; - virtual ~RenderAPI() { delete &context; }; + RenderAPI(RenderContext* ctx); + virtual ~RenderAPI(); public: void* operator new(size_t size) { return ::operator new(size, GlobalPool()); } void operator delete(void* p) {} + static RenderAPI* Ptr(); public: + virtual void Init() = 0; virtual void Shutdown() = 0; @@ -27,6 +29,8 @@ namespace api { virtual void DrawStaticMesh(Mesh& mesh) = 0; virtual void LoadShader(Shader& shader) = 0; + virtual ImagePtr CreateTexture(TextureDesc desc) = 0; + virtual ImageViewPtr CreateTextureView(TextureViewDesc 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 f80ce4d..01a6d64 100644 --- a/engine/modules/engine/render/include/render/type.h +++ b/engine/modules/engine/render/include/render/type.h @@ -17,48 +17,24 @@ namespace api { SAMPLE_COUNT_16 = 16, SAMPLE_COUNT_COUNT = 5, }; - struct BufferDesc { - static BufferDesc Make() { - return {}; - } - }; - using ImagePtr = void*; - struct TextureDesc { - using Key = uint32_t; - ImagePtr image; - static TextureDesc Make() { - return {}; - } - }; - struct AttachmentDesc { - ImagePtr image; - TinyImageFormat colorFormat; - SampleCount sampleCount; - static AttachmentDesc Make() { - return {}; - } - TextureDesc ToTexture() { - return TextureDesc{image}; - } - }; - enum class TargetBufferFlags : uint32_t { - NONE = 0x0u, //!< No buffer selected. - COLOR0 = 0x00000001u, //!< Color buffer selected. - COLOR1 = 0x00000002u, //!< Color buffer selected. - COLOR2 = 0x00000004u, //!< Color buffer selected. - COLOR3 = 0x00000008u, //!< Color buffer selected. - COLOR4 = 0x00000010u, //!< Color buffer selected. - COLOR5 = 0x00000020u, //!< Color buffer selected. - COLOR6 = 0x00000040u, //!< Color buffer selected. - COLOR7 = 0x00000080u, //!< Color buffer selected. + enum class TargetBufferFlags : uint32_t { + NONE = 0x0u, //!< No buffer selected. + COLOR0 = 0x00000001u, //!< Color buffer selected. + COLOR1 = 0x00000002u, //!< Color buffer selected. + COLOR2 = 0x00000004u, //!< Color buffer selected. + COLOR3 = 0x00000008u, //!< Color buffer selected. + COLOR4 = 0x00000010u, //!< Color buffer selected. + COLOR5 = 0x00000020u, //!< Color buffer selected. + COLOR6 = 0x00000040u, //!< Color buffer selected. + COLOR7 = 0x00000080u, //!< Color buffer selected. - COLOR = COLOR0, //!< \deprecated - COLOR_ALL = COLOR0 | COLOR1 | COLOR2 | COLOR3 | COLOR4 | COLOR5 | COLOR6 | COLOR7, - DEPTH = 0x10000000u, //!< Depth buffer selected. - STENCIL = 0x20000000u, //!< Stencil buffer selected. - DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected. - ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected. - }; + COLOR = COLOR0, //!< \deprecated + COLOR_ALL = COLOR0 | COLOR1 | COLOR2 | COLOR3 | COLOR4 | COLOR5 | COLOR6 | COLOR7, + DEPTH = 0x10000000u, //!< Depth buffer selected. + STENCIL = 0x20000000u, //!< Stencil buffer selected. + DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected. + ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected. + }; enum class ResourceState { // The initial layout after the creation of the VkImage. We use this to denote the state before @@ -81,9 +57,65 @@ namespace api { // For color attachments, but also used when the image is a sampler. // TODO: explore separate layout policies for attachment+sampling and just attachment. COLOR_ATTACHMENT, - // For color attachment MSAA resolves. - COLOR_ATTACHMENT_RESOLVE, }; + enum class TextureDimension + { + TEX_1D = 0x01, + TEX_2D = 0x02, + TEX_3D = 0x04, + TEX_CUBE = 0x08, + }; + using ImagePtr = void*; + using ImageViewPtr = void*; + struct BufferDesc { + static BufferDesc Make() { + return {}; + } + }; + 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; + }; + struct TextureViewDesc { + ImagePtr image; + TinyImageFormat format : 16; + ResourceState state : 8; + TextureDimension dimension: 8; + uint32_t baseArrayLayer : 8; + uint32_t layerCount : 8; + uint32_t baseMipLevel : 8; + uint32_t levelCount : 8; + }; + struct AttachmentDesc { + ImagePtr image; + 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; + return *this; + } + TextureDesc ToTexture() { + return TextureDesc{ + .image = image, + .width = width, + .height = height, + }; + } + }; struct TextureBarrier { TextureDesc mTexture; @@ -114,4 +146,23 @@ namespace api { const TextureBarrier* pTextureBarriers; uint32_t textureBarriersCount; }; +} +#include "meta/hash.h" +namespace std { + template<> + struct hash + { + size_t operator()(const api::TextureViewDesc& key) const noexcept + { + return meta::MurmurHashFn(key); + } + }; + template<> + struct hash + { + size_t operator()(const api::TextureDesc& key) const noexcept + { + return meta::MurmurHashFn(key); + } + }; } \ No newline at end of file diff --git a/engine/modules/engine/render/src/graph/frame_graph.cpp b/engine/modules/engine/render/src/graph/frame_graph.cpp index 646c8cd..e29caf3 100644 --- a/engine/modules/engine/render/src/graph/frame_graph.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph.cpp @@ -1,13 +1,44 @@ #include "render/graph/frame_graph.h" -#include "render/graph/frame_graph_builder.h" #include "render/renderapi.h" 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.state != k2.state) 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::AddPresent(const FrameGraphEdgePtr& edge) + { + FrameGraphNodePtr node_ptr{ mGraph.addNode()}; + RenderPassBuilder builder{ this, node_ptr }; + builder.Read(edge, ResourceState::PRESENT); + mNodes.push_back(node_ptr); + return node_ptr; + } FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor) { FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor }; RenderPassBuilder builder{ this, node_ptr }; - setup(*this, builder); - mNodes.push_back(node_ptr); + if(setup(*this, builder)) + mNodes.push_back(node_ptr); return node_ptr; } FrameGraphEdgePtr FrameGraph::CreateTexture(const TextureSetupFunction& setup) @@ -63,8 +94,7 @@ namespace api { } void FrameGraph::ExecutePresentPass(RenderPassNode* node, FRenderView& view) { - RenderPassContext context{}; - std::get(node->executor)(*this, context); + ExecuteResourceBarriers(node); } void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view) { @@ -104,6 +134,7 @@ namespace api { } textureBarrier.push_back(barrier); } + resource->sourceState = edge.targetState; }); if (bufferBarrier.empty() && textureBarrier.empty()) { return; @@ -123,4 +154,24 @@ namespace api { fn(edge.resource, edge); } } + ImagePtr FrameGraph::ResolveTexture(TextureDesc desc) + { + auto it = mResourcePool.find(desc); + if (it != mResourcePool.end()) { + return it->second; + } + ImagePtr image = RenderAPI::Ptr()->CreateTexture(desc); + mResourcePool.emplace(desc, image); + return image; + } + ImageViewPtr FrameGraph::ResolveTextureView(TextureViewDesc desc) + { + auto it = mResourceViewPool.find(desc); + if (it != mResourceViewPool.end()) { + return it->second; + } + ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(desc); + mResourceViewPool.emplace(desc, view); + return 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 de9805a..13cabc0 100644 --- a/engine/modules/engine/render/src/graph/frame_graph_builder.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph_builder.cpp @@ -1,16 +1,12 @@ -#include "render/graph/frame_graph_builder.h" +#include "render/graph/frame_graph.h" #include "render/pass/render_pass.h" +#include "meta/enum.h" namespace api { FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name) { node->name = name; return *this; } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Pass(RenderPass* pass) - { - node->pass = pass; - return *this; - } FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state) { FrameGraphEdgePtr edge{}; @@ -44,34 +40,39 @@ namespace api { return *this; } - FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& edge) + FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& refEdge, ResourceState state) { - if (!edge) { return *this; } + if (!refEdge) { return *this; } + FrameGraphEdgePtr edge{ refEdge , state}; node->inEdges.emplace_back(edge); - edge->targets.emplace_back(node); - if(edge->source) - graph.mGraph.addEdge(edge->source.ref, node.ref); + 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& edge) + FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state) { - if (!edge) { return *this; } + if (!refEdge) { return *this; } + FrameGraphEdgePtr edge{ refEdge , state }; node->outEdges.emplace_back(edge); - edge->targets.emplace_back(node); - if (edge->source) - graph.mGraph.addEdge(node.ref, edge->source.ref); + refEdge->targets.emplace_back(node); + if (refEdge->source) + graph.mGraph.addEdge(node.ref, refEdge->source.ref); return *this; } - FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Name(pmr::Name name) + FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Present(const FrameGraphEdgePtr& refEdge, ResourceState state) { + Write(refEdge, state); + graph.mNodes.push_back(node); + graph.AddPresent(refEdge); + return *this; + } + FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc, ResourceState state) + { + desc.image = nullptr; edge->name = name; - return *this; - } - FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(ImagePtr& ptr, AttachmentDesc desc, ResourceState state) - { - edge.ppImage = &ptr; - edge.targetState = state; edge->resource = desc; + edge.targetState = state; 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 5444400..c382118 100644 --- a/engine/modules/engine/render/src/graph/type.cpp +++ b/engine/modules/engine/render/src/graph/type.cpp @@ -1,4 +1,5 @@ #include "render/graph/type.h" +#include "render/renderapi.h" namespace api { void FrameGraphEdgePtr::Resolve(FrameGraph* graph) { @@ -17,8 +18,42 @@ namespace api { if (*imageptr) { return; } - if (ppImage) { - *imageptr = *ppImage; + TextureDesc desc = graph->Resource(resource->name); + if (!desc.image) { + graph->ResolveTexture(desc); + } + else { + *imageptr = desc.image; } } + void FrameGraphEdgePtr::ResolveView(FrameGraph* graph) + { + if (!resource) { + Make(); + } + if (resource->IsAttachment()) { + AttachmentDesc& attach = resource->CastTo(); + TextureViewDesc view{}; + view.image = attach.image; + view.format = attach.colorFormat; + view.state = targetState; + view.baseArrayLayer = 0; + view.baseMipLevel = 0; + view.layerCount = 1; + view.levelCount = 1; + view.dimension = attach.dimension; + attach.imageView = graph->ResolveTextureView(view); + } + } + FrameGraphNodePtr::FrameGraphNodePtr(GraphNodeRef ref, NodeType type) + : ref(ref), type(type) + { + node = new (FramePool()) RenderPassNode(); + node->executor = [&](FrameGraph& graph, RenderPassContext& ctx) { + this->Presnet(graph, ctx); + }; + } + void FrameGraphNodePtr::Presnet(FrameGraph&, RenderPassContext&) { + + } } diff --git a/engine/modules/engine/render/src/pass/demo_pass.cpp b/engine/modules/engine/render/src/pass/demo_pass.cpp index 2e10b8e..3605af8 100644 --- a/engine/modules/engine/render/src/pass/demo_pass.cpp +++ b/engine/modules/engine/render/src/pass/demo_pass.cpp @@ -1,18 +1,20 @@ #include "render/pass/demo_pass.h" namespace api { - void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) + bool DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) { AttachmentDesc surface{}; - surface.colorFormat = TinyImageFormat_B8G8R8A8_UNORM; + surface.FromTexture(graph.mSurface); + surface.colorFormat = TinyImageFormat_B8G8R8A8_SRGB; surface.sampleCount = SAMPLE_COUNT_1; + surface.dimension = TextureDimension::TEX_2D; auto edge = graph.CreateTexture( [=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) { - builder.Name("import") - .Import(graph.mSurface.image, surface, ResourceState::PRESENT); + builder.Import("surface", surface, ResourceState::COLOR_ATTACHMENT); }); builder.Name("MiniPass") - .Write(edge); + .Present(edge, edge.targetState); + return false; } void DemoPass::Execute(FrameGraph&, RenderPassContext&) { diff --git a/engine/modules/engine/render/xmake.lua b/engine/modules/engine/render/xmake.lua index a83b5e7..de7c9ba 100644 --- a/engine/modules/engine/render/xmake.lua +++ b/engine/modules/engine/render/xmake.lua @@ -1,6 +1,6 @@ static_component("render","engine") add_includedirs("3rdparty", {public = true}) - add_headerfiles("include/**.h", "impl/*.inl") + add_headerfiles("include/**.h", "include/**.inl", "impl/*.inl") add_files("src/**.cpp") add_deps("asset", "zlib", "core") add_syslinks("user32", {public = true}) diff --git a/engine/modules/render/vulkan/include/vkn/type.h b/engine/modules/render/vulkan/include/vkn/type.h index 9b68be9..eb05ebf 100644 --- a/engine/modules/render/vulkan/include/vkn/type.h +++ b/engine/modules/render/vulkan/include/vkn/type.h @@ -15,6 +15,14 @@ namespace vkn { using voidFn = std::function; using commandFn = std::function; using api::TargetBufferFlags; + using api::ResourceBarrierDesc; + using api::TextureViewDesc; + using api::ImageViewPtr; + using api::ImagePtr; + using api::TextureDimension; + using api::SampleCount; + using api::ResourceState; + using api::TextureDesc; constexpr string_view VulkanEngineName = "vulkan"; constexpr uint8_t MAX_SUPPORTED_RENDER_TARGET_COUNT = 8u; @@ -37,8 +45,15 @@ namespace vkn { uint8_t initialColorLayoutMask;// 1 byte uint8_t needsResolveMask; // 1 byte }; + struct FramebufferKey { + VkRenderPass pass; + VkImageView imageViews[MAX_SUPPORTED_RENDER_TARGET_COUNT * 2 + 1]; + uint32_t attachmentCount; + uint32_t width; + uint32_t height; + uint32_t layers; + }; } -#include "meta/hash.h" namespace std { template<> struct hash @@ -48,4 +63,12 @@ namespace std { return meta::MurmurHashFn(key); } }; + template<> + struct hash + { + size_t operator()(const vkn::FramebufferKey& key) const noexcept + { + return meta::MurmurHashFn(key); + } + }; } \ No newline at end of file diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api.h b/engine/modules/render/vulkan/include/vkn/vulkan_api.h index da5fa3e..afea79a 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api.h @@ -13,7 +13,6 @@ namespace vkn { using api::Mesh; using api::Shader; using api::RenderPassNode; - using api::ResourceBarrierDesc; struct VulkanContext : public api::RenderContext { VkFence surfaceFence;; VkSemaphore surfaceSemaphore; @@ -26,6 +25,7 @@ namespace vkn { Backend backend; table MeshTable; table RenderPassCache; + table FramebufferCache; public: VulkanAPI(); @@ -36,6 +36,8 @@ namespace vkn { void DrawStaticMesh(Mesh& mesh)override; void LoadShader(Shader& shader)override; + ImagePtr CreateTexture(TextureDesc desc)override; + ImageViewPtr CreateTextureView(TextureViewDesc desc)override; void BeginFrame()override; void EndFrame()override; @@ -43,7 +45,7 @@ namespace vkn { void EndRenderPass(RenderPassNode* node) override; void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override; - VkPipeline GetPipeline(); + VkPipeline GetPipeline() { return nullptr; }; VkRenderPass GetRenderPass(RenderPassKey& config); Backend& GetBackend() { 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 1f0802b..a2e5332 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api_help.h @@ -10,6 +10,13 @@ namespace vkn { VkImageLayout mSrcState; VkImageLayout mDstState; }; - VkImageLayout GetVkLayout(ResourceState layout); - VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier); + VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit); + VkImageLayout vkApiGetImageLayout(ResourceState layout); + VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier); + VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit); + VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState); + VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize); + VkImageType vkApiGetImageType(TextureDimension dimension); + VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize); + VkSampleCountFlagBits vkApiGetSmpleCountFlag(SampleCount sample); } \ 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 9d87598..0af8001 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_window.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_window.h @@ -20,13 +20,14 @@ namespace vkn { }; class VulkanSwapchain { private: + friend class VulkanWindow; Device& mDevice; VkSwapchainKHR mPtr; int mFrames; - pmr::vector mSurfaces{GlobalPool()}; + pmr::vector mSurfaces{ GlobalPool() }; pmr::vector mCommands{ GlobalPool() }; - pmr::vector mFences{ GlobalPool() }; - pmr::vector mSemaphores{ GlobalPool() }; + pmr::vector mFences{ GlobalPool() }; + pmr::vector mSemaphores{ GlobalPool() }; public: VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); void Aquire(VulkanContext& ctx); diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index 49e0227..5570582 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -8,7 +8,7 @@ #include "render/asset/mesh.h" #include "meta/enum.h" #include "tinyimageformat/tinyimageformat_apis.h" - +#include "zlog.h" namespace vkn { inline bool operator==(const RenderPassKey& k1, const RenderPassKey& k2) { if (k1.initialColorLayoutMask != k2.initialColorLayoutMask) return false; @@ -24,6 +24,17 @@ namespace vkn { if (k1.subpassMask != k2.subpassMask) return false; return true; } + 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) @@ -67,6 +78,65 @@ namespace vkn { void VulkanAPI::LoadShader(Shader& shader) { } + ImagePtr 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, + .flags = vkApiGetImageCreateFlag(desc.dimension, desc.arraySize), + .imageType = vkApiGetImageType(desc.dimension), + .format = (VkFormat)TinyImageFormat_ToVkFormat(desc.format), + .extent = { + .width = (uint32_t)desc.width, + .height = (uint32_t)desc.height, + .depth = (uint32_t)desc.depth, + }, + .mipLevels = desc.mipLevel, + .arrayLayers = desc.arraySize, + .samples = vkApiGetSmpleCountFlag(desc.sampleCount), + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = vkApiGetImageUsageFlags(desc.state), + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = NULL, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED + }; + return ImagePtr(); + } + ImageViewPtr VulkanAPI::CreateTextureView(TextureViewDesc desc) + { + VkImageViewCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = (VkImage)desc.image; + createInfo.viewType = vkApiGetImageViewType(desc.dimension, desc.layerCount); + createInfo.format = (VkFormat)TinyImageFormat_ToVkFormat(desc.format); + + // components字段允许调整颜色通道的最终的映射逻辑 + // 比如,我们可以将所有颜色通道映射为红色通道,以实现单色纹理,我们也可以将通道映射具体的常量数值0和1 + // 这里用默认的 + createInfo.components.r = VK_COMPONENT_SWIZZLE_R; + createInfo.components.g = VK_COMPONENT_SWIZZLE_G; + createInfo.components.b = VK_COMPONENT_SWIZZLE_B; + createInfo.components.a = VK_COMPONENT_SWIZZLE_A; + + // subresourceRangle字段用于描述图像的使用目标是什么,以及可以被访问的有效区域 + // 这个图像用作填充color还是depth stencil等 + createInfo.subresourceRange.aspectMask = vkApiGetImageAspectMask(createInfo.format, false); + // 默认处理所有Mipmap + createInfo.subresourceRange.baseMipLevel = desc.baseMipLevel; + createInfo.subresourceRange.levelCount = desc.levelCount; + // 默认处理所有Layers + createInfo.subresourceRange.baseArrayLayer = desc.baseArrayLayer; + createInfo.subresourceRange.layerCount = desc.layerCount; + + VkImageView imageView; + vkCreateImageView(backend.GetDevice().Ptr(), &createInfo, nullptr, &imageView); + return (ImageViewPtr)imageView; + } void VulkanAPI::BeginFrame() { VulkanContext& ctx = *(VulkanContext*)&context; @@ -77,7 +147,21 @@ namespace vkn { { VulkanContext& ctx = *(VulkanContext*)&context; ctx.command.EndRecord(); - ctx.command.Submit(Backend::RenderWorker->GetQueue().Ptr(), ctx.surfaceFence); + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; // 等待渲染阶段 + VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore }; + VkSemaphore signalSemaphores[] = { ctx.presentSemaphore };// 渲染完成信号量 + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &ctx.command.Ptr(); + + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, ctx.surfaceFence); window.Present(ctx); } void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) { @@ -86,12 +170,11 @@ namespace vkn { bufferBarriers.reserve(desc.bufferBarriersCount); pmr::vector imageBarriers{ FramePool() }; imageBarriers.reserve(desc.textureBarriersCount); - using api::ResourceState; VkPipelineStageFlags srcStageMask = 0, dstStageMask = 0; for (uint32_t i = 0; i < desc.textureBarriersCount; i++) { auto& barrier = desc.pTextureBarriers[i]; - auto desc = GetVkTextureTransition(srcStageMask, dstStageMask, barrier); + auto desc = vkApiGetTextureTransition(srcStageMask, dstStageMask, barrier); imageBarriers.push_back(desc); } if (dstStageMask == 0) { @@ -101,24 +184,66 @@ namespace vkn { } void VulkanAPI::BeginRenderPass(RenderPassNode* node) { - RenderPassKey config{}; + RenderPassKey config{}; + FramebufferKey frameKey{.layers = 1}; + VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 }; int i = 0; for (auto& it : node->outEdges) { if (it->IsAttachment()) { auto& desc = it->CastTo(); + config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat); - config.samples = (VkSampleCountFlagBits)desc.sampleCount; + config.samples = vkApiGetSmpleCountFlag(desc.sampleCount); TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i); config.clear |= flag; + it.ResolveView(&graph); + frameKey.imageViews[i] = (VkImageView)desc.imageView; + frameKey.height = desc.height; + frameKey.width = desc.width; + + //clearValues[i] = i++; } } - node->pass = GetRenderPass(config); + frameKey.attachmentCount = i; + VkRenderPass pass = GetRenderPass(config); + frameKey.pass = pass; + auto it = FramebufferCache.find(frameKey); + VkFramebuffer framebuffer = it->second; + if (it == FramebufferCache.end()) { + VkFramebufferCreateInfo framebufferInfo = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = pass, + .attachmentCount = frameKey.attachmentCount, + .pAttachments = frameKey.imageViews, + .width = frameKey.width, + .height = frameKey.height, + .layers = frameKey.layers + }; + vkCreateFramebuffer(backend.GetDevice().Ptr(), &framebufferInfo, nullptr, &framebuffer); + FramebufferCache.emplace(frameKey, framebuffer); + } + VkRect2D renderAarea = { + .offset = {0,0}, + .extent = {frameKey.width,frameKey.height} + }; + VkRenderPassBeginInfo beginInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .pNext = VK_NULL_HANDLE, + .renderPass = pass, + .framebuffer = framebuffer, + .renderArea = renderAarea, + .clearValueCount = frameKey.attachmentCount, + .pClearValues = clearValues + }; + VulkanContext& ctx = *(VulkanContext*)&context; + vkCmdBeginRenderPass(ctx.command.Ptr(), &beginInfo, VK_SUBPASS_CONTENTS_INLINE); } void VulkanAPI::EndRenderPass(RenderPassNode* node) { - + VulkanContext& ctx = *(VulkanContext*)&context; + vkCmdEndRenderPass(ctx.command.Ptr()); } VkRenderPass VulkanAPI::GetRenderPass(RenderPassKey& config) { auto it = RenderPassCache.find(config); @@ -221,6 +346,7 @@ namespace vkn { const TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i); const bool clear = any(config.clear & flag); const bool discard = any(config.discardStart & flag); + VkImageLayout layout = vkApiGetAttachmentLayout(config.colorFormat[i], true); attachments[attachmentIndex++] = { .format = config.colorFormat[i], .samples = config.samples, @@ -228,9 +354,8 @@ namespace vkn { .storeOp = kEnableStore, .stencilLoadOp = kDontCare, .stencilStoreOp = kDisableStore, - .initialLayout = ((!discard && config.initialColorLayoutMask & (1 << i)) || clear) - ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + .initialLayout = layout, + .finalLayout = layout, }; } // Nulling out the zero-sized lists is necessary to avoid VK_ERROR_OUT_OF_HOST_MEMORY on Adreno. diff --git a/engine/modules/render/vulkan/src/vulkan_api_help.cpp b/engine/modules/render/vulkan/src/vulkan_api_help.cpp index 03fcc6f..062c87e 100644 --- a/engine/modules/render/vulkan/src/vulkan_api_help.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api_help.cpp @@ -1,7 +1,32 @@ #include #include "vkn/vulkan_api_help.h" +#include "meta/enum.h" namespace vkn { - VkImageLayout GetVkLayout(ResourceState layout) { + VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit) + { + switch (format) + { + // Depth + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT: + return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + // Stencil + case VK_FORMAT_S8_UINT: + return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL; + // Depth/stencil + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + if (includeStencilBit) + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + // Assume everything else is Color + default: + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + } + VkImageLayout vkApiGetImageLayout(ResourceState layout) { switch (layout) { case ResourceState::UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED; @@ -19,31 +44,22 @@ namespace vkn { return VK_IMAGE_LAYOUT_GENERAL; case ResourceState::PRESENT: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - // Filament sometimes samples from one miplevel while writing to another level in the - // same texture (e.g. bloom does this). Moreover we'd like to avoid lots of expensive - // layout transitions. So, keep it simple and use GENERAL for all color-attachable - // textures. case ResourceState::COLOR_ATTACHMENT: - return VK_IMAGE_LAYOUT_GENERAL; - case ResourceState::COLOR_ATTACHMENT_RESOLVE: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } } - VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier) { + VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier) { VkAccessFlags srcAccessMask, dstAccessMask; VkPipelineStageFlags srcStage, dstStage; switch (barrier.mSrcState) { case ResourceState::UNDEFINED: - srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + srcAccessMask = 0; + srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; break; case ResourceState::COLOR_ATTACHMENT: - srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case ResourceState::READ_WRITE: srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; @@ -69,23 +85,16 @@ namespace vkn { srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; - case ResourceState::COLOR_ATTACHMENT_RESOLVE: - srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; case ResourceState::PRESENT: - srcAccessMask = VK_ACCESS_NONE; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; break; } switch (barrier.mDstState) { case ResourceState::COLOR_ATTACHMENT: - dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT - | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT - | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dstStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT - | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; case ResourceState::READ_WRITE: dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; @@ -115,10 +124,9 @@ namespace vkn { VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; break; case ResourceState::PRESENT: - case ResourceState::COLOR_ATTACHMENT_RESOLVE: case ResourceState::UNDEFINED: - dstAccessMask = 0; - dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; break; } mSrcStage |= srcStage; @@ -134,12 +142,95 @@ namespace vkn { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = srcAccessMask, .dstAccessMask = dstAccessMask, - .oldLayout = GetVkLayout(barrier.mSrcState), - .newLayout = GetVkLayout(barrier.mDstState), + .oldLayout = vkApiGetImageLayout(barrier.mSrcState), + .newLayout = vkApiGetImageLayout(barrier.mDstState), .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = (VkImage)barrier.mTexture.image, .subresourceRange = subresources }; } + VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit) + { + VkImageAspectFlags result = 0; + switch (format) + { + // Depth + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_X8_D24_UNORM_PACK32: + case VK_FORMAT_D32_SFLOAT: + result = VK_IMAGE_ASPECT_DEPTH_BIT; + break; + // Stencil + case VK_FORMAT_S8_UINT: + result = VK_IMAGE_ASPECT_STENCIL_BIT; + break; + // Depth/stencil + case VK_FORMAT_D16_UNORM_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + result = VK_IMAGE_ASPECT_DEPTH_BIT; + if (includeStencilBit) + result |= VK_IMAGE_ASPECT_STENCIL_BIT; + break; + // Assume everything else is Color + default: + result = VK_IMAGE_ASPECT_COLOR_BIT; + break; + } + return result; + } + VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState) + { + VkImageUsageFlags usageFlags = 0; + if (any(startState & ResourceState::COLOR_ATTACHMENT)) + usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + else if (any(startState & ResourceState::DEPTH_ATTACHMENT)) + usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + return usageFlags; + } + VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize) + { + if (any(dimension & TextureDimension::TEX_1D)) { + return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D; + } + if (any(dimension & TextureDimension::TEX_CUBE)) { + return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE; + } + if (any(dimension & TextureDimension::TEX_2D)) { + return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; + } + if (any(dimension & TextureDimension::TEX_3D)) { + return VK_IMAGE_VIEW_TYPE_3D; + } + return VK_IMAGE_VIEW_TYPE_MAX_ENUM; + } + VkImageType vkApiGetImageType(TextureDimension dimension) + { + if (any(dimension & TextureDimension::TEX_1D)) { + return VK_IMAGE_TYPE_1D; + } + if (any(dimension & TextureDimension::TEX_2D)) { + return VK_IMAGE_TYPE_2D; + } + if (any(dimension & TextureDimension::TEX_3D)) { + return VK_IMAGE_TYPE_3D; + } + return VK_IMAGE_TYPE_MAX_ENUM; + } + VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize) + { + VkImageCreateFlags flag{}; + if (any(dimension & TextureDimension::TEX_CUBE)) { + flag |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; + } + if (arraySize > 0) { + flag |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR; + } + return flag; + } + VkSampleCountFlagBits vkApiGetSmpleCountFlag(SampleCount sample) + { + return (VkSampleCountFlagBits)sample; + } } \ No newline at end of file diff --git a/engine/modules/render/vulkan/src/vulkan_window.cpp b/engine/modules/render/vulkan/src/vulkan_window.cpp index ba4ffbc..31f62fb 100644 --- a/engine/modules/render/vulkan/src/vulkan_window.cpp +++ b/engine/modules/render/vulkan/src/vulkan_window.cpp @@ -8,6 +8,7 @@ #include "asset/resource_system.h" #include "zlog.h" #include +#include namespace vkn { bool VulkanWindow::CreateRender(CreatePFN createPFN, VulkanWindowArgs& args) { @@ -21,6 +22,7 @@ namespace vkn { args.width = mWidth; args.height = mHeight; mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args); + api->graph.mSurface = mSwapchain->mSurfaces[0]; return true; } VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args) @@ -63,8 +65,16 @@ namespace vkn { mSurfaces.reserve(mFrames); mCommands.reserve(mFrames); mSemaphores.reserve(mFrames + mFrames); + TextureDesc desc{}; + desc.width = args.width; + desc.height = args.height; + desc.format = TinyImageFormat_FromVkFormat((TinyImageFormat_VkFormat)args.imageFormat); + desc.state = ResourceState::PRESENT; + desc.sampleCount = SampleCount::SAMPLE_COUNT_1; + desc.arraySize = 1; + desc.mipLevel = 1; + desc.depth = 1; for (int i = 0; i < mFrames; i++) { - api::TextureDesc desc; desc.image = swapchain_images[i]; mSurfaces.push_back(desc); mSemaphores.push_back(mDevice.CreateSemaphore()); @@ -91,7 +101,7 @@ namespace vkn { { VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.pWaitSemaphores = &ctx.surfaceSemaphore; + presentInfo.pWaitSemaphores = &ctx.presentSemaphore; presentInfo.waitSemaphoreCount = 1; presentInfo.pSwapchains = &mPtr; presentInfo.swapchainCount = 1; diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index fada0fe..c53c13f 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -5,14 +5,6 @@ #include "render/pass/demo_pass.h" #include using namespace api; -FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor) -{ - FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor }; - RenderPassBuilder builder{ this, node_ptr }; - setup(*this, builder); - mNodes.push_back(node_ptr); - return node_ptr; -} RenderAPI* API; void ZWorldModule::OnLoad(int argc, char** argv) { @@ -24,6 +16,7 @@ void ZWorldModule::OnLoad(int argc, char** argv) if (!window->CreateRender(&SDL_Vulkan_CreateSurface, args)) { zlog::errorf("SDL_Vulkan_CreateSurface failed {}", SDL_GetError()); } + API->Init(); API->context.views.push_back({}); }