diff --git a/engine/modules/engine/asset/include/asset/res/resource_config.h b/engine/modules/engine/asset/include/asset/res/resource_config.h index ee4b58a..5f083bd 100644 --- a/engine/modules/engine/asset/include/asset/res/resource_config.h +++ b/engine/modules/engine/asset/include/asset/res/resource_config.h @@ -25,7 +25,6 @@ namespace api { class ShaderProgram , class Asset , class Texture - , class FrameBuffer >; template concept is_resource_v = requires { typename Resource::BaseResource; }; diff --git a/engine/modules/engine/render/impl/renderapi_impl.inl b/engine/modules/engine/render/impl/renderapi_impl.inl index 7cc37c9..e4bbe83 100644 --- a/engine/modules/engine/render/impl/renderapi_impl.inl +++ b/engine/modules/engine/render/impl/renderapi_impl.inl @@ -2,4 +2,16 @@ #include "render/module.h" namespace api { IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render); + void RenderAPI::RenderView(FRenderView& view) + { + graph.Compile(); + graph.Execute(view); + graph.Clear(); + } + void RenderAPI::Render() + { + for (auto view : context.views) { + RenderView(view); + } + } } \ No newline at end of file diff --git a/engine/modules/engine/render/impl/window_impl.inl b/engine/modules/engine/render/impl/window_impl.inl index dc40492..0edce80 100644 --- a/engine/modules/engine/render/impl/window_impl.inl +++ b/engine/modules/engine/render/impl/window_impl.inl @@ -1,11 +1,11 @@ #include "render/window.h" namespace api { - inline Window::Window(CreatePFN func, const Args& args, int width, int height) noexcept : mHeight(height), mWidth(width) + inline Window::Window(CreatePFN createPFN, const Args& args, int width, int height) noexcept : mHeight(height), mWidth(width) { - uint32_t windowFlags = SDL_WINDOW_SHOWN; + uint32_t windowFlags = args.windowFlags | SDL_WINDOW_SHOWN; windowFlags |= args.resizeable ? SDL_WINDOW_RESIZABLE : 0; windowFlags |= args.headless ? SDL_WINDOW_HIDDEN : 0; // Even if we're in headless mode, we still need to create a window, otherwise SDL will not poll events. - mPtr = func(args.title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, windowFlags); + mPtr = createPFN(args.title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, windowFlags); } } \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/asset/framebuffer.h b/engine/modules/engine/render/include/render/asset/framebuffer.h deleted file mode 100644 index 359c361..0000000 --- a/engine/modules/engine/render/include/render/asset/framebuffer.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "desc/attachment_desc.h" -namespace api { - class Attachment; - class FrameBuffer : public Resource - { - public: - pmr::vector mAttachments{}; - Attachment* mDepthAttach{}; - Attachment* mStencilAttach{}; - Vector2 mSize; - public: - Vector2 Size() const { return mSize; } - const Attachment& DepthAttachment()const { return *mDepthAttach; } - const Attachment& GetAttachment(size_t index)const { return *mAttachments[index]; } - }; -} \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/asset/texture.h b/engine/modules/engine/render/include/render/asset/texture.h new file mode 100644 index 0000000..4973568 --- /dev/null +++ b/engine/modules/engine/render/include/render/asset/texture.h @@ -0,0 +1,8 @@ +#pragma once +#include "asset/asset.h" +namespace api { + class Texture : public Resource + { + public: + }; +} \ 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 989e93f..0ea6e5b 100644 --- a/engine/modules/engine/render/include/render/graph/frame_graph.h +++ b/engine/modules/engine/render/include/render/graph/frame_graph.h @@ -1,6 +1,7 @@ #pragma once #include "type.h" namespace api { + struct FRenderView; class FrameGraph { public: @@ -18,13 +19,13 @@ namespace api { FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup); void Compile(); - void Execute(); + void Execute(FRenderView& view); void Clear(); public: - void ExecuteRenderPass(RenderPassNode* node); - void ExecutePresentPass(RenderPassNode* node); - void ExecuteComputePass(RenderPassNode* node); - void ExecuteCopyPass(RenderPassNode* node); + void ExecuteRenderPass(RenderPassNode* node, FRenderView& view); + void ExecutePresentPass(RenderPassNode* node, FRenderView& view); + void ExecuteComputePass(RenderPassNode* node, FRenderView& view); + void ExecuteCopyPass(RenderPassNode* node, FRenderView& view); }; } \ 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 4804492..bd5b95c 100644 --- a/engine/modules/engine/render/include/render/graph/type.h +++ b/engine/modules/engine/render/include/render/graph/type.h @@ -1,5 +1,6 @@ #pragma once -#include "render/asset/framebuffer.h" +#include "asset/asset.h" +#include "render/type.h" #include "lemon/list_graph.h" #include namespace api { diff --git a/engine/modules/engine/render/include/render/render_context.h b/engine/modules/engine/render/include/render/render_context.h index 1411310..c330243 100644 --- a/engine/modules/engine/render/include/render/render_context.h +++ b/engine/modules/engine/render/include/render/render_context.h @@ -1,7 +1,13 @@ #pragma once #include "type.h" namespace api { + struct RenderContext; + struct FRenderView { + RenderContext* context; + }; struct RenderContext { - + pmr::vector views; + uint32_t frame{ 0 }; + uint32_t presentFrame{ 0 }; }; } \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/renderapi.h b/engine/modules/engine/render/include/render/renderapi.h index dc9d5aa..67be439 100644 --- a/engine/modules/engine/render/include/render/renderapi.h +++ b/engine/modules/engine/render/include/render/renderapi.h @@ -2,14 +2,15 @@ #include "singleton.h" #include "pmr/frame_allocator.h" #include "render_context.h" +#include "graph/frame_graph.h" namespace api { class Mesh; class Shader; - class Camera; - class RenderNode; class RENDER_API RenderAPI : public Singleton { public: + RenderContext* ctx; + FrameGraph graph; RenderAPI() {}; virtual ~RenderAPI() {}; public: @@ -28,5 +29,7 @@ namespace api { virtual void BeginFrame() = 0; virtual void EndFrame() = 0; + virtual void RenderView(FRenderView& view); + void Render(); }; } \ 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 a763de3..0a13a10 100644 --- a/engine/modules/engine/render/include/render/type.h +++ b/engine/modules/engine/render/include/render/type.h @@ -1,4 +1,5 @@ #pragma once +#include namespace api { enum class GraphicsAPI { @@ -6,4 +7,14 @@ namespace api { Vulkan, D3D12 }; + struct TextureDesc { + static TextureDesc Make() { + return {}; + } + }; + struct AttachmentDesc { + static AttachmentDesc Make() { + return {}; + } + }; } \ No newline at end of file diff --git a/engine/modules/engine/render/include/render/window.h b/engine/modules/engine/render/include/render/window.h index a9a5a12..601d07e 100644 --- a/engine/modules/engine/render/include/render/window.h +++ b/engine/modules/engine/render/include/render/window.h @@ -11,6 +11,7 @@ namespace api { SDL_Window* mPtr = nullptr; struct Args { const char* title; + uint32_t windowFlags = 0; bool resizeable = true; bool headless = false; }; diff --git a/engine/modules/engine/render/src/asset/framebuffer.cpp b/engine/modules/engine/render/src/asset/framebuffer.cpp deleted file mode 100644 index 65ae676..0000000 --- a/engine/modules/engine/render/src/asset/framebuffer.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "render/asset/framebuffer.h" -namespace api { - -} \ No newline at end of file diff --git a/engine/modules/engine/render/src/asset/texture.cpp b/engine/modules/engine/render/src/asset/texture.cpp new file mode 100644 index 0000000..d8ba1f8 --- /dev/null +++ b/engine/modules/engine/render/src/asset/texture.cpp @@ -0,0 +1,4 @@ +#include "render/asset/texture.h" +namespace api { + +} \ 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 bfa7014..9c7d3ca 100644 --- a/engine/modules/engine/render/src/graph/frame_graph.cpp +++ b/engine/modules/engine/render/src/graph/frame_graph.cpp @@ -27,21 +27,21 @@ namespace api { }); mNodes.erase(end, mNodes.end()); } - void FrameGraph::Execute() + void FrameGraph::Execute(FRenderView& view) { for (auto node : mNodes) { switch (node.type) { case FrameGraphNodePtr::Render: - ExecuteRenderPass(node.node); + ExecuteRenderPass(node.node, view); break; case FrameGraphNodePtr::Present: - ExecuteComputePass(node.node); + ExecuteRenderPass(node.node, view); break; case FrameGraphNodePtr::Compute: - ExecuteRenderPass(node.node); + ExecuteComputePass(node.node, view); break; case FrameGraphNodePtr::Copy: - ExecuteCopyPass(node.node); + ExecuteCopyPass(node.node, view); break; } } @@ -51,22 +51,22 @@ namespace api { mGraph.clear(); mNodes.clear(); } - void FrameGraph::ExecuteRenderPass(RenderPassNode* node) + void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view) { RenderPassContext context{}; std::get(node->executor)(*this, context); } - void FrameGraph::ExecutePresentPass(RenderPassNode* node) + void FrameGraph::ExecutePresentPass(RenderPassNode* node, FRenderView& view) { RenderPassContext context{}; std::get(node->executor)(*this, context); } - void FrameGraph::ExecuteComputePass(RenderPassNode* node) + void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view) { ComputePassContext context{}; std::get(node->executor)(*this, context); } - void FrameGraph::ExecuteCopyPass(RenderPassNode* node) + void FrameGraph::ExecuteCopyPass(RenderPassNode* node, FRenderView& view) { CopyPassContext context{}; std::get(node->executor)(*this, context); diff --git a/engine/modules/render/vulkan/include/vkn/type.h b/engine/modules/render/vulkan/include/vkn/type.h index e6bf94e..347cbb6 100644 --- a/engine/modules/render/vulkan/include/vkn/type.h +++ b/engine/modules/render/vulkan/include/vkn/type.h @@ -14,4 +14,13 @@ namespace vkn { class CommandBuffer; using voidFn = std::function; using commandFn = std::function; + + struct MeshVAO + { + uint32_t indexCount = 0; // 索引数量 + VkBuffer indexBuffer = VK_NULL_HANDLE; + uint32_t vertexCount = 0; // 顶点数量 + VkBuffer vertexBuffer = VK_NULL_HANDLE; + bool inUse = false; + }; } diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_api.h b/engine/modules/render/vulkan/include/vkn/vulkan_api.h index 1ef01ec..ef044de 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_api.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_api.h @@ -10,6 +10,10 @@ namespace vkn { using api::Guid; using api::Mesh; using api::Shader; + class VulkanContext : public api::RenderContext { + public: + VkSemaphore surfaceSemaphore; + }; class VULKAN_API VulkanAPI : public api::RenderAPI { private: VulkanWindow& window; diff --git a/engine/modules/render/vulkan/include/vkn/vulkan_window.h b/engine/modules/render/vulkan/include/vkn/vulkan_window.h index 599fe48..5001ff4 100644 --- a/engine/modules/render/vulkan/include/vkn/vulkan_window.h +++ b/engine/modules/render/vulkan/include/vkn/vulkan_window.h @@ -1,9 +1,14 @@ #pragma once #include "type.h" #include "render/window.h" +#include +namespace api { + class RenderContext; +} namespace vkn { class Device; - struct VulkanWindowArgs { + using RenderContext = api::RenderContext; + struct VULKAN_API VulkanWindowArgs { uint32_t frames; uint32_t width; uint32_t height; @@ -25,9 +30,10 @@ namespace vkn { pmr::vector mSemaphores{ GlobalPool() }; public: VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); - + void Aquire(RenderContext& ctx); + void Present(RenderContext& ctx); }; - class VulkanWindow : public api::Window { + class VULKAN_API VulkanWindow : public api::Window { private: VulkanSwapchain* mSwapchain; public: @@ -37,9 +43,12 @@ namespace vkn { void operator delete(void* p) {} public: using api::Window::Window; - void CreateRender(VulkanWindowArgs& args); + using CreatePFN = decltype(&SDL_Vulkan_CreateSurface); + bool CreateRender(CreatePFN createPFN, VulkanWindowArgs& args); static VulkanWindow* Ptr() { return (VulkanWindow*)api::Window::Ptr(); } + void Aquire(RenderContext& ctx) { mSwapchain->Aquire(ctx); } + void Present(RenderContext& ctx) { mSwapchain->Present(ctx); }; }; } \ No newline at end of file diff --git a/engine/modules/render/vulkan/include/vkn/wrapper/buffer.h b/engine/modules/render/vulkan/include/vkn/wrapper/buffer.h index 7010c88..356502e 100644 --- a/engine/modules/render/vulkan/include/vkn/wrapper/buffer.h +++ b/engine/modules/render/vulkan/include/vkn/wrapper/buffer.h @@ -1,14 +1,6 @@ #pragma once #include "vkn/type.h" namespace vkn { - struct MeshVAO - { - uint32_t indexCount = 0; // 索引数量 - VkBuffer indexBuffer = VK_NULL_HANDLE; - uint32_t vertexCount = 0; // 顶点数量 - VkBuffer vertexBuffer = VK_NULL_HANDLE; - bool inUse = false; - }; struct Buffer { VkBuffer* ppBuffer; void* pCpuData; diff --git a/engine/modules/render/vulkan/src/vulkan_api.cpp b/engine/modules/render/vulkan/src/vulkan_api.cpp index 331a3b6..1fb5eea 100644 --- a/engine/modules/render/vulkan/src/vulkan_api.cpp +++ b/engine/modules/render/vulkan/src/vulkan_api.cpp @@ -48,10 +48,10 @@ namespace vkn { } void VulkanAPI::BeginFrame() { - + window.Aquire(context); } void VulkanAPI::EndFrame() { - + window.Present(context); } } diff --git a/engine/modules/render/vulkan/src/vulkan_window.cpp b/engine/modules/render/vulkan/src/vulkan_window.cpp index 346aee2..a2eebca 100644 --- a/engine/modules/render/vulkan/src/vulkan_window.cpp +++ b/engine/modules/render/vulkan/src/vulkan_window.cpp @@ -4,21 +4,21 @@ #include "vkn/vulkan_api.h" #include "vkn/backend.h" #include "zlog.h" -#include #include namespace vkn { - void VulkanWindow::CreateRender(VulkanWindowArgs& args) + bool VulkanWindow::CreateRender(CreatePFN createPFN, VulkanWindowArgs& args) { VulkanAPI* api = VulkanAPI::Ptr(); Backend& backend = api->GetBackend(); VkInstance instance = backend.GetInstance().Ptr(); VkSurfaceKHR surface; - if (!SDL_Vulkan_CreateSurface(mPtr, instance, &surface)) { - zlog::error("SDL_Vulkan_CreateSurface failed! {}", SDL_GetError()); + if (!createPFN(mPtr, instance, &surface)) { + return false; } args.width = mWidth; args.height = mHeight; mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args); + return true; } VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args) : mDevice(device) @@ -50,9 +50,37 @@ namespace vkn { if (result != VK_SUCCESS) { zlog::error("Failed to create swap chain."); } - pmr::vector swapchain_images{FramePool()}; - mFrames = args.frames; + pmr::vector swapchain_images{ FramePool() }; + uint32_t imageCount = 0; + vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, nullptr); + swapchain_images.resize(imageCount); + vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data()); + + } + void VulkanSwapchain::Aquire(RenderContext& ctx) + { + VkFence surfaceFence = mFences[ctx.frame]; + VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame]; + if (vkWaitForFences(mDevice.Ptr(), 1, &surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) + throw std::runtime_error("Failed to wait for fence!"); + vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame); + vkResetFences(mDevice.Ptr(), 1, &surfaceFence); + } + void VulkanSwapchain::Present(RenderContext& ctx) + { + VkSwapchainKHR swapChains[] = { mPtr }; + VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore }; + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.pWaitSemaphores = waitSemaphores; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.swapchainCount = 1; + presentInfo.pImageIndices = &ctx.presentFrame; + presentInfo.pResults = VK_NULL_HANDLE; + Backend::RenderWorker->Present(presentInfo); + ctx.frame = (ctx.frame + 1) % mFrames; } VkExtent2D VulkanWindowArgs::EnableImageExtent2D(VkSurfaceCapabilitiesKHR& capabilities) { diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index ebc25f3..00c7b9f 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -1,25 +1,33 @@ +#include "zlog.h" #include "zworld.h" #include "vkn/vulkan_window.h" #include "vkn/vulkan_api.h" +#include "render/pass/demo_pass.h" #include using namespace api; +RenderAPI* API; void ZWorldModule::OnLoad(int argc, char** argv) { // 创建窗口 - new vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" }, 1080, 720); - new vkn::VulkanAPI(); + auto window = new vkn::VulkanWindow(&SDL_CreateWindow, { "zengine" , SDL_WINDOW_VULKAN }, 1080, 720); + API = new vkn::VulkanAPI(); + auto args = vkn::VulkanWindowArgs::Default(); + args.frames = 3; + if (!window->CreateRender(&SDL_Vulkan_CreateSurface, args)) { + zlog::errorf("SDL_Vulkan_CreateSurface failed {}", SDL_GetError()); + } + API->context.views.push_back({}); } void ZWorldModule::OnUnload() { - + API = nullptr; } void ZWorldModule::MainLoop() { bool running = true; SDL_Event event_; - auto RenderAPI = RenderAPI::Ptr(); while (running) { // 处理事件 while (SDL_PollEvent(&event_)) { @@ -27,7 +35,9 @@ void ZWorldModule::MainLoop() running = false; } } - RenderAPI->BeginFrame(); - RenderAPI->EndFrame(); + API->graph.AddRenderPass(); + API->BeginFrame(); + API->Render(); + API->EndFrame(); } }