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 0a681ec..d12fa9c 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph.h @@ -10,7 +10,8 @@ namespace api { public: TextureDesc mSurface; table mResourceTable; - table mResourceTable; + table mResourcePool; + table mResourceViewPool; lemon::ListGraph mGraph; pmr::vector mNodes{FramePool()}; public: diff --git a/engine/modules/engine/render/include/render/graph/type.h b/engine/modules/engine/render/include/render/graph/type.h index f62bdd9..64d08c6 100644 --- a/engine/modules/engine/render/include/render/graph/type.h +++ b/engine/modules/engine/render/include/render/graph/type.h @@ -40,7 +40,6 @@ namespace api { Name name; ResourceState sourceState; Resource resource; - ImagePtr image; FrameGraphNodePtr source; pmr::vector targets{ FramePool() }; template @@ -72,6 +71,7 @@ namespace api { FrameResource* operator ->()const { return resource; } + void Resolve(FrameGraph* graph); }; using RenderPassEdgeIterFn = std::function; struct RenderPassNode { 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 cb001fd..8a4de5e 100644 --- a/engine/modules/engine/render/include/render/pass/demo_pass.h +++ b/engine/modules/engine/render/include/render/pass/demo_pass.h @@ -7,4 +7,5 @@ namespace api { static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder); static void Execute(FrameGraph&, RenderPassContext&); }; + } \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/type.h b/engine/modules/engine/render/include/render/type.h index 4144159..f80ce4d 100644 --- a/engine/modules/engine/render/include/render/type.h +++ b/engine/modules/engine/render/include/render/type.h @@ -8,6 +8,15 @@ namespace api { Vulkan, D3D12 }; + enum SampleCount + { + SAMPLE_COUNT_1 = 1, + SAMPLE_COUNT_2 = 2, + SAMPLE_COUNT_4 = 4, + SAMPLE_COUNT_8 = 8, + SAMPLE_COUNT_16 = 16, + SAMPLE_COUNT_COUNT = 5, + }; struct BufferDesc { static BufferDesc Make() { return {}; @@ -15,6 +24,7 @@ namespace api { }; using ImagePtr = void*; struct TextureDesc { + using Key = uint32_t; ImagePtr image; static TextureDesc Make() { return {}; @@ -23,6 +33,7 @@ namespace api { struct AttachmentDesc { ImagePtr image; TinyImageFormat colorFormat; + SampleCount sampleCount; static AttachmentDesc Make() { return {}; } diff --git a/engine/modules/engine/render/src/graph/frame_graph.cpp b/engine/modules/engine/render/src/graph/frame_graph.cpp index 1ed2199..646c8cd 100644 --- a/engine/modules/engine/render/src/graph/frame_graph.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph.cpp @@ -80,17 +80,8 @@ namespace api { { pmr::vector bufferBarrier{FramePool()}; pmr::vector textureBarrier{ FramePool() }; - node->ForeachEdge([&](FrameResource* resource, FrameGraphEdgePtr edge) { - if (edge) { - if (!edge->image) { - if (edge.ppImage) { - edge->image = *edge.ppImage; - } - else { - edge->image = Resource(""); - } - } - } + node->ForeachEdge([&, this](FrameResource* resource, FrameGraphEdgePtr edge) { + edge.Resolve(this); if (!edge || edge.targetState == resource->sourceState) { return; } 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 e21a737..de9805a 100644 --- a/engine/modules/engine/render/src/graph/frame_graph_builder.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph_builder.cpp @@ -18,7 +18,6 @@ namespace api { resource = edge.Make(); resource->source = node; resource->resource = desc; - edge->image = desc.image; node->inEdges.push_back(edge); return *this; } @@ -41,7 +40,6 @@ namespace api { resource = edge.Make(); resource->source = node; resource->resource = desc; - edge->image = desc.image; node->outEdges.push_back(edge); return *this; } @@ -74,7 +72,6 @@ namespace api { edge.ppImage = &ptr; edge.targetState = state; edge->resource = desc; - edge->image = desc.image; 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 new file mode 100644 index 0000000..5444400 --- /dev/null +++ b/engine/modules/engine/render/src/graph/type.cpp @@ -0,0 +1,24 @@ +#include "render/graph/type.h" +namespace api { + void FrameGraphEdgePtr::Resolve(FrameGraph* graph) + { + if (!resource) { + Make(); + } + ImagePtr* imageptr; + if (resource->IsAttachment()) { + AttachmentDesc& desc = resource->CastTo(); + imageptr = &desc.image; + } + else if (resource->IsTexture()) { + TextureDesc& desc = resource->CastTo(); + imageptr = &desc.image; + } + if (*imageptr) { + return; + } + if (ppImage) { + *imageptr = *ppImage; + } + } +} diff --git a/engine/modules/engine/render/src/pass/demo_pass.cpp b/engine/modules/engine/render/src/pass/demo_pass.cpp index de3fa6a..2e10b8e 100644 --- a/engine/modules/engine/render/src/pass/demo_pass.cpp +++ b/engine/modules/engine/render/src/pass/demo_pass.cpp @@ -4,11 +4,12 @@ namespace api { void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) { AttachmentDesc surface{}; - surface.colorFormat = TinyImageFormat_B8G8R8_UNORM; + surface.colorFormat = TinyImageFormat_B8G8R8A8_UNORM; + surface.sampleCount = SAMPLE_COUNT_1; auto edge = graph.CreateTexture( [=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) { builder.Name("import") - .Import(graph.mSurface, surface, ResourceState::PRESENT); + .Import(graph.mSurface.image, surface, ResourceState::PRESENT); }); builder.Name("MiniPass") .Write(edge); diff --git a/engine/modules/engine/zlib/include/meta/enum.h b/engine/modules/engine/zlib/include/meta/enum.h index f80ba10..cd9f25c 100644 --- a/engine/modules/engine/zlib/include/meta/enum.h +++ b/engine/modules/engine/zlib/include/meta/enum.h @@ -4,6 +4,17 @@ namespace meta { concept is_enum_t = requires { std::is_enum_v; }; } template +inline constexpr Enum operator|=(Enum& lhs, Enum rhs) noexcept { + using underlying = std::underlying_type_t; + lhs = Enum(underlying(lhs) | underlying(rhs)); + return lhs; +} +template +inline constexpr Enum operator|(Enum lhs, Enum rhs) noexcept { + using underlying = std::underlying_type_t; + return Enum(underlying(lhs) | underlying(rhs)); +} +template inline constexpr Enum operator&(Enum lhs, Enum rhs) noexcept { using underlying = std::underlying_type_t; return Enum(underlying(lhs) & underlying(rhs)); diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api.h b/engine/modules/render/vulkan/include/vkn/vulkan_api.h index dadc410..da5fa3e 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api.h @@ -2,6 +2,7 @@ #include "type.h" #include "asset/res/guid.h" #include "render/renderapi.h" +#include "wrapper/commandbuffer.h" #include "backend.h" namespace vkn { class Backend; @@ -14,9 +15,10 @@ namespace vkn { using api::RenderPassNode; using api::ResourceBarrierDesc; struct VulkanContext : public api::RenderContext { + VkFence surfaceFence;; VkSemaphore surfaceSemaphore; VkSemaphore presentSemaphore; - VkCommandBuffer command; + CommandBuffer command; }; class VULKAN_API VulkanAPI : public api::RenderAPI { private: diff --git a/engine/modules/render/vulkan/include/vkn/wrapper/commandbuffer.h b/engine/modules/render/vulkan/include/vkn/wrapper/commandbuffer.h index b72724c..f7d9166 100644 --- a/engine/modules/render/vulkan/include/vkn/wrapper/commandbuffer.h +++ b/engine/modules/render/vulkan/include/vkn/wrapper/commandbuffer.h @@ -5,6 +5,7 @@ namespace vkn { protected: VkCommandBuffer mPtr; public: + CommandBuffer() : mPtr(nullptr) {}; CommandBuffer(VkCommandBuffer ptr) : mPtr(ptr) {}; VkCommandBuffer& Ptr() { return mPtr; diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index fc554a3..49e0227 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -69,11 +69,16 @@ namespace vkn { } void VulkanAPI::BeginFrame() { - window.Aquire(*(VulkanContext*)&context); + VulkanContext& ctx = *(VulkanContext*)&context; + window.Aquire(ctx); + ctx.command.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); } void VulkanAPI::EndFrame() { - window.Present(*(VulkanContext*)&context); + VulkanContext& ctx = *(VulkanContext*)&context; + ctx.command.EndRecord(); + ctx.command.Submit(Backend::RenderWorker->GetQueue().Ptr(), ctx.surfaceFence); + window.Present(ctx); } void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) { VulkanContext& ctx = *(VulkanContext*)&context; @@ -89,7 +94,10 @@ namespace vkn { auto desc = GetVkTextureTransition(srcStageMask, dstStageMask, barrier); imageBarriers.push_back(desc); } - vkCmdPipelineBarrier(ctx.command, srcStageMask, dstStageMask, 0, 0,NULL, 0, NULL, imageBarriers.size(), imageBarriers.data()); + if (dstStageMask == 0) { + dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + } + vkCmdPipelineBarrier(ctx.command.Ptr(), srcStageMask, dstStageMask, 0, 0, NULL, 0, NULL, imageBarriers.size(), imageBarriers.data()); } void VulkanAPI::BeginRenderPass(RenderPassNode* node) { @@ -99,6 +107,10 @@ namespace vkn { if (it->IsAttachment()) { auto& desc = it->CastTo(); config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat); + config.samples = (VkSampleCountFlagBits)desc.sampleCount; + + TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i); + config.clear |= flag; i++; } } diff --git a/engine/modules/render/vulkan/src/vulkan_api_help.cpp b/engine/modules/render/vulkan/src/vulkan_api_help.cpp index 9112cbc..03fcc6f 100644 --- a/engine/modules/render/vulkan/src/vulkan_api_help.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api_help.cpp @@ -123,6 +123,13 @@ namespace vkn { } mSrcStage |= srcStage; mDstStage |= dstStage; + VkImageSubresourceRange subresources{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; return VkImageMemoryBarrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = srcAccessMask, @@ -132,7 +139,7 @@ namespace vkn { .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = (VkImage)barrier.mTexture.image, - //.subresourceRange = transition.subresources, + .subresourceRange = subresources }; } } \ 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 80b397e..ba4ffbc 100644 --- a/engine/modules/render/vulkan/src/vulkan_window.cpp +++ b/engine/modules/render/vulkan/src/vulkan_window.cpp @@ -79,6 +79,7 @@ namespace vkn { VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame]; ctx.surface = mSurfaces[ctx.frame]; ctx.command = mCommands[ctx.frame]; + ctx.surfaceFence = surfaceFence; ctx.surfaceSemaphore = surfaceSemaphore; ctx.presentSemaphore = mSemaphores[ctx.frame + mFrames]; if (vkWaitForFences(mDevice.Ptr(), 1, &surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) diff --git a/engine/modules/render/vulkan/src/wrapper/device_create.cpp b/engine/modules/render/vulkan/src/wrapper/device_create.cpp index 2046044..f09ed93 100644 --- a/engine/modules/render/vulkan/src/wrapper/device_create.cpp +++ b/engine/modules/render/vulkan/src/wrapper/device_create.cpp @@ -24,6 +24,7 @@ namespace vkn { void DeviceCreator::AddWindowExtension() { AddExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + //AddExtension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); #ifdef Z_RENDER_DEBUG AddLayer("VK_LAYER_KHRONOS_validation"); AddLayer("VK_LAYER_RENDERDOC_Capture"); diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index 9cd2725..fada0fe 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -5,6 +5,14 @@ #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) {