This commit is contained in:
ouczbs 2024-09-01 22:32:29 +08:00
parent f6e755ea3f
commit f8913cd7d2
21 changed files with 146 additions and 69 deletions

View File

@ -25,7 +25,6 @@ namespace api {
class ShaderProgram
, class Asset
, class Texture
, class FrameBuffer
>;
template<typename Resource>
concept is_resource_v = requires { typename Resource::BaseResource; };

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "desc/attachment_desc.h"
namespace api {
class Attachment;
class FrameBuffer : public Resource<FrameBuffer>
{
public:
pmr::vector<Attachment*> 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]; }
};
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "asset/asset.h"
namespace api {
class Texture : public Resource<Texture>
{
public:
};
}

View File

@ -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);
};
}

View File

@ -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 <functional>
namespace api {

View File

@ -1,7 +1,13 @@
#pragma once
#include "type.h"
namespace api {
struct RenderContext;
struct FRenderView {
RenderContext* context;
};
struct RenderContext {
pmr::vector<FRenderView> views;
uint32_t frame{ 0 };
uint32_t presentFrame{ 0 };
};
}

View File

@ -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<RenderAPI>
{
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();
};
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <cstdint>
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 {};
}
};
}

View File

@ -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;
};

View File

@ -1,4 +0,0 @@
#include "render/asset/framebuffer.h"
namespace api {
}

View File

@ -0,0 +1,4 @@
#include "render/asset/texture.h"
namespace api {
}

View File

@ -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<RenderPassExecuteFunction>(node->executor)(*this, context);
}
void FrameGraph::ExecutePresentPass(RenderPassNode* node)
void FrameGraph::ExecutePresentPass(RenderPassNode* node, FRenderView& view)
{
RenderPassContext context{};
std::get<RenderPassExecuteFunction>(node->executor)(*this, context);
}
void FrameGraph::ExecuteComputePass(RenderPassNode* node)
void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view)
{
ComputePassContext context{};
std::get<ComputePassExecuteFunction>(node->executor)(*this, context);
}
void FrameGraph::ExecuteCopyPass(RenderPassNode* node)
void FrameGraph::ExecuteCopyPass(RenderPassNode* node, FRenderView& view)
{
CopyPassContext context{};
std::get<CopyPassExecuteFunction>(node->executor)(*this, context);

View File

@ -14,4 +14,13 @@ namespace vkn {
class CommandBuffer;
using voidFn = std::function<void()>;
using commandFn = std::function<void(CommandBuffer& cmd)>;
struct MeshVAO
{
uint32_t indexCount = 0; // 索引数量
VkBuffer indexBuffer = VK_NULL_HANDLE;
uint32_t vertexCount = 0; // 顶点数量
VkBuffer vertexBuffer = VK_NULL_HANDLE;
bool inUse = false;
};
}

View File

@ -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;

View File

@ -1,9 +1,14 @@
#pragma once
#include "type.h"
#include "render/window.h"
#include <SDL2/SDL_vulkan.h>
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<VkSemaphore> 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); };
};
}

View File

@ -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;

View File

@ -48,10 +48,10 @@ namespace vkn {
}
void VulkanAPI::BeginFrame()
{
window.Aquire(context);
}
void VulkanAPI::EndFrame()
{
window.Present(context);
}
}

View File

@ -4,21 +4,21 @@
#include "vkn/vulkan_api.h"
#include "vkn/backend.h"
#include "zlog.h"
#include <SDL2/SDL_vulkan.h>
#include <algorithm>
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<VkImage> swapchain_images{FramePool()};
mFrames = args.frames;
pmr::vector<VkImage> 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)
{

View File

@ -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 <iostream>
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<DemoPass>();
API->BeginFrame();
API->Render();
API->EndFrame();
}
}