This commit is contained in:
ouczbs 2024-09-22 20:26:49 +08:00
parent 3ab7bb46f6
commit d814786d26
18 changed files with 123 additions and 53 deletions

View File

@ -10,6 +10,7 @@ namespace api {
} }
void RenderAPI::Render() void RenderAPI::Render()
{ {
graph.mSurface = context.surface;
for (auto view : context.views) { for (auto view : context.views) {
RenderView(view); RenderView(view);
} }

View File

@ -2,6 +2,7 @@
#include "math/vector2.h" #include "math/vector2.h"
#include "render_enum.h" #include "render_enum.h"
namespace api { namespace api {
/*
class Texture; class Texture;
struct Attachment struct Attachment
{ {
@ -43,5 +44,5 @@ namespace api {
static AttachmentDesc Make() { static AttachmentDesc Make() {
return {}; return {};
} }
}; };*/
} }

View File

@ -1,9 +1,13 @@
#pragma once #pragma once
#include "asset/asset.h" #include "asset/asset.h"
#include "render/type.h"
namespace api { namespace api {
class Texture : public Resource<Texture> class Texture : public Resource<Texture>
{ {
public: public:
void* mPtr; TextureDesc mDesc;
void* mPtr;
public:
Texture(TextureDesc& desc);
}; };
} }

View File

@ -8,8 +8,8 @@ namespace api {
class TextureBuilder; class TextureBuilder;
class RenderPassBuilder; class RenderPassBuilder;
public: public:
RscHandle<Texture> mSurface; TextureDesc mSurface;
table<Name, RscHandle<Texture>> mResourceTable; table<Name, TextureDesc> mResourceTable;
lemon::ListGraph mGraph; lemon::ListGraph mGraph;
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()}; pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
public: public:
@ -23,7 +23,7 @@ namespace api {
void Compile(); void Compile();
void Execute(FRenderView& view); void Execute(FRenderView& view);
void Clear(); void Clear();
RscHandle<Texture> Resource(Name name) { TextureDesc Resource(Name name) {
auto it = mResourceTable.find(name); auto it = mResourceTable.find(name);
if (it == mResourceTable.end()) { if (it == mResourceTable.end()) {
return {}; return {};
@ -36,6 +36,6 @@ namespace api {
void ExecuteComputePass(RenderPassNode* node, FRenderView& view); void ExecuteComputePass(RenderPassNode* node, FRenderView& view);
void ExecuteCopyPass(RenderPassNode* node, FRenderView& view); void ExecuteCopyPass(RenderPassNode* node, FRenderView& view);
void ExecuteResourceBarriers(RenderPassNode* node, RenderPassEdgeIterFn fn); void ExecuteResourceBarriers(RenderPassNode* node);
}; };
} }

View File

@ -10,9 +10,9 @@ namespace api {
: graph(*graph) , node(node) {}; : graph(*graph) , node(node) {};
FrameGraph::RenderPassBuilder& Name(pmr::Name name); FrameGraph::RenderPassBuilder& Name(pmr::Name name);
FrameGraph::RenderPassBuilder& Pass(RenderPass* pass); FrameGraph::RenderPassBuilder& Pass(RenderPass* pass);
FrameGraph::RenderPassBuilder& Read(TextureDesc desc); FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state);
FrameGraph::RenderPassBuilder& Write(TextureDesc desc); FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state);
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc); FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state);
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& edge); FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& edge);
}; };
struct FrameGraph::TextureBuilder { struct FrameGraph::TextureBuilder {

View File

@ -7,7 +7,8 @@ namespace api {
}; };
struct RenderContext { struct RenderContext {
pmr::vector<FRenderView> views; pmr::vector<FRenderView> views;
uint32_t frame{ 0 }; TextureDesc surface;
uint32_t presentFrame{ 0 }; uint32_t frame{ 0 };
uint32_t presentFrame{ 0 };
}; };
} }

View File

@ -13,12 +13,15 @@ namespace api {
return {}; return {};
} }
}; };
using ImagePtr = void*;
struct TextureDesc { struct TextureDesc {
ImagePtr image;
static TextureDesc Make() { static TextureDesc Make() {
return {}; return {};
} }
}; };
struct AttachmentDesc { struct AttachmentDesc {
ImagePtr image;
TinyImageFormat colorFormat; TinyImageFormat colorFormat;
static AttachmentDesc Make() { static AttachmentDesc Make() {
return {}; return {};
@ -69,7 +72,7 @@ namespace api {
}; };
struct TextureBarrier struct TextureBarrier
{ {
//Texture* pTexture; TextureDesc mTexture;
ResourceState mSrcState; ResourceState mSrcState;
ResourceState mDstState; ResourceState mDstState;
uint8_t mBeginOnly : 1; uint8_t mBeginOnly : 1;

View File

@ -1,4 +1,7 @@
#include "render/asset/texture.h" #include "render/asset/texture.h"
namespace api { namespace api {
Texture::Texture(TextureDesc& desc)
{
}
} }

View File

@ -27,7 +27,7 @@ namespace api {
} }
return !degree; return !degree;
}); });
mNodes.erase(end, mNodes.end()); //mNodes.erase(end, mNodes.end());
} }
void FrameGraph::Execute(FRenderView& view) void FrameGraph::Execute(FRenderView& view)
{ {
@ -55,6 +55,7 @@ namespace api {
} }
void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view) void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view)
{ {
ExecuteResourceBarriers(node);
RenderAPI::Ptr()->BeginRenderPass(node); RenderAPI::Ptr()->BeginRenderPass(node);
RenderPassContext context{}; RenderPassContext context{};
std::get<RenderPassExecuteFunction>(node->executor)(*this, context); std::get<RenderPassExecuteFunction>(node->executor)(*this, context);
@ -75,7 +76,7 @@ namespace api {
CopyPassContext context{}; CopyPassContext context{};
std::get<CopyPassExecuteFunction>(node->executor)(*this, context); std::get<CopyPassExecuteFunction>(node->executor)(*this, context);
} }
void FrameGraph::ExecuteResourceBarriers(RenderPassNode* node, RenderPassEdgeIterFn fn) void FrameGraph::ExecuteResourceBarriers(RenderPassNode* node)
{ {
pmr::vector<BufferBarrier> bufferBarrier{FramePool()}; pmr::vector<BufferBarrier> bufferBarrier{FramePool()};
pmr::vector<TextureBarrier> textureBarrier{ FramePool() }; pmr::vector<TextureBarrier> textureBarrier{ FramePool() };
@ -104,7 +105,7 @@ namespace api {
desc.pBufferBarriers = bufferBarrier.data(); desc.pBufferBarriers = bufferBarrier.data();
desc.textureBarriersCount = textureBarrier.size(); desc.textureBarriersCount = textureBarrier.size();
desc.pTextureBarriers = textureBarrier.data(); desc.pTextureBarriers = textureBarrier.data();
RenderAPI::Ptr()->ExecuteResourceBarriers(desc);
} }
void RenderPassNode::ForeachEdge(RenderPassEdgeIterFn fn) { void RenderPassNode::ForeachEdge(RenderPassEdgeIterFn fn) {
for (auto& edge : inEdges) { for (auto& edge : inEdges) {

View File

@ -11,10 +11,10 @@ namespace api {
node->pass = pass; node->pass = pass;
return *this; return *this;
} }
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state)
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc)
{ {
FrameGraphEdgePtr edge{}; FrameGraphEdgePtr edge{};
edge.targetState = state;
resource = edge.Make(); resource = edge.Make();
resource->source = node; resource->source = node;
resource->resource = desc; resource->resource = desc;
@ -22,9 +22,10 @@ namespace api {
return *this; return *this;
} }
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(TextureDesc desc) FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(BufferDesc desc, ResourceState state)
{ {
FrameGraphEdgePtr edge{}; FrameGraphEdgePtr edge{};
edge.targetState = state;
resource = edge.Make(); resource = edge.Make();
resource->source = node; resource->source = node;
resource->resource = desc; resource->resource = desc;
@ -32,11 +33,14 @@ namespace api {
return *this; return *this;
} }
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc) FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc, ResourceState state)
{ {
if (resource) { FrameGraphEdgePtr edge{};
resource->resource = desc; edge.targetState = state;
} resource = edge.Make();
resource->source = node;
resource->resource = desc;
node->outEdges.push_back(edge);
return *this; return *this;
} }

View File

@ -3,26 +3,11 @@
namespace api { namespace api {
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
{ {
auto edge = graph.CreateTexture( AttachmentDesc surface{};
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) { surface.image = graph.mSurface.image;
builder.Name("import") surface.colorFormat = TinyImageFormat_B8G8R8_UNORM;
.Import(graph.Resource("demo_input")); builder.Name("MiniPass")
}); .Attach(surface, ResourceState::PRESENT);
builder.Name("DemoPass")
.Read(TextureDesc::Make())
.Read(edge)
.Write(TextureDesc::Make())
.Attach(AttachmentDesc::Make());
auto parent_node = builder.node;
graph.AddRenderPass(
[=](FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) {
builder.Name("DemoPassSub")
.Read(edge)
.Read(parent_node->GetOutput(0));
},
[](FrameGraph& graph, RenderPassContext& context) {
});
} }
void DemoPass::Execute(FrameGraph&, RenderPassContext&) void DemoPass::Execute(FrameGraph&, RenderPassContext&)
{ {

View File

@ -27,5 +27,8 @@ namespace vkn {
Queue& GetQueue() { Queue& GetQueue() {
return mQueue; return mQueue;
} }
VkCommandBuffer AllocateBuffer(VkCommandBufferLevel level) {
return mCommandPool.AllocateBuffer(level);
}
}; };
} }

View File

@ -16,6 +16,7 @@ namespace vkn {
struct VulkanContext : public api::RenderContext { struct VulkanContext : public api::RenderContext {
VkSemaphore surfaceSemaphore; VkSemaphore surfaceSemaphore;
VkSemaphore presentSemaphore; VkSemaphore presentSemaphore;
VkCommandBuffer command;
}; };
class VULKAN_API VulkanAPI : public api::RenderAPI { class VULKAN_API VulkanAPI : public api::RenderAPI {
private: private:

View File

@ -1,4 +1,15 @@
#include "type.h" #include "type.h"
namespace vkn { namespace vkn {
using api::ResourceState;
using api::TextureBarrier;
struct VkTextureTransitionDesc {
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
VkPipelineStageFlags srcStage;
VkPipelineStageFlags dstStage;
VkImageLayout mSrcState;
VkImageLayout mDstState;
};
VkImageLayout GetVkLayout(ResourceState layout);
VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier);
} }

View File

@ -5,6 +5,7 @@
namespace vkn { namespace vkn {
class Device; class Device;
struct VulkanContext; struct VulkanContext;
using api::TextureDesc;
struct VULKAN_API VulkanWindowArgs { struct VULKAN_API VulkanWindowArgs {
uint32_t frames; uint32_t frames;
uint32_t width; uint32_t width;
@ -22,7 +23,8 @@ namespace vkn {
Device& mDevice; Device& mDevice;
VkSwapchainKHR mPtr; VkSwapchainKHR mPtr;
int mFrames; int mFrames;
//pmr::vector<Image*> mSurfaces{GlobalPool()}; pmr::vector<TextureDesc> mSurfaces{GlobalPool()};
pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() };
pmr::vector<VkFence> mFences{ GlobalPool() }; pmr::vector<VkFence> mFences{ GlobalPool() };
pmr::vector<VkSemaphore> mSemaphores{ GlobalPool() }; pmr::vector<VkSemaphore> mSemaphores{ GlobalPool() };
public: public:

View File

@ -1,5 +1,6 @@
#include "vkn/vulkan_api.h" #include "vkn/vulkan_api.h"
#include "vkn/vulkan_window.h" #include "vkn/vulkan_window.h"
#include "vkn/vulkan_api_help.h"
#include "vkn/wrapper/buffer.h" #include "vkn/wrapper/buffer.h"
#include "vkn/wrapper/device.h" #include "vkn/wrapper/device.h"
#include "vkn/thread/buffer_worker.h" #include "vkn/thread/buffer_worker.h"
@ -7,6 +8,7 @@
#include "render/asset/mesh.h" #include "render/asset/mesh.h"
#include "meta/enum.h" #include "meta/enum.h"
#include "tinyimageformat/tinyimageformat_apis.h" #include "tinyimageformat/tinyimageformat_apis.h"
namespace vkn { namespace vkn {
inline bool operator==(const RenderPassKey& k1, const RenderPassKey& k2) { inline bool operator==(const RenderPassKey& k1, const RenderPassKey& k2) {
if (k1.initialColorLayoutMask != k2.initialColorLayoutMask) return false; if (k1.initialColorLayoutMask != k2.initialColorLayoutMask) return false;
@ -74,16 +76,20 @@ namespace vkn {
window.Present(*(VulkanContext*)&context); window.Present(*(VulkanContext*)&context);
} }
void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) { void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
VkCommandBuffer cmd; VulkanContext& ctx = *(VulkanContext*)&context;
pmr::vector<VkBufferMemoryBarrier> bufferBarriers{ FramePool() }; pmr::vector<VkBufferMemoryBarrier> bufferBarriers{ FramePool() };
bufferBarriers.reserve(desc.bufferBarriersCount); bufferBarriers.reserve(desc.bufferBarriersCount);
pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() }; pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() };
imageBarriers.reserve(desc.textureBarriersCount); imageBarriers.reserve(desc.textureBarriersCount);
using api::ResourceState; using api::ResourceState;
VkPipelineStageFlags srcStageMask, dstStageMask;
for (uint32_t i = 0; i < desc.textureBarriersCount; i++) for (uint32_t i = 0; i < desc.textureBarriersCount; i++)
{ {
auto& barrier = desc.pTextureBarriers[i]; auto& barrier = desc.pTextureBarriers[i];
auto desc = GetVkTextureTransition(srcStageMask, dstStageMask, barrier);
imageBarriers.push_back(desc);
} }
vkCmdPipelineBarrier(ctx.command, srcStageMask, dstStageMask, 0, 0,NULL, 0, NULL, imageBarriers.size(), imageBarriers.data());
} }
void VulkanAPI::BeginRenderPass(RenderPassNode* node) void VulkanAPI::BeginRenderPass(RenderPassNode* node)
{ {

View File

@ -1,10 +1,35 @@
#include <tuple> #include <tuple>
#include "vkn/vulkan_api_help.h" #include "vkn/vulkan_api_help.h"
namespace vkn { namespace vkn {
using api::ResourceState; VkImageLayout GetVkLayout(ResourceState layout) {
inline std::tuple<VkAccessFlags, VkAccessFlags, VkPipelineStageFlags, VkPipelineStageFlags, switch (layout) {
VkImageLayout, VkImageLayout> case ResourceState::UNDEFINED:
getVkTransition(const api::TextureBarrier& barrier) { return VK_IMAGE_LAYOUT_UNDEFINED;
case ResourceState::READ_WRITE:
return VK_IMAGE_LAYOUT_GENERAL;
case ResourceState::READ_ONLY:
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
case ResourceState::TRANSFER_SRC:
return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
case ResourceState::TRANSFER_DST:
return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
case ResourceState::DEPTH_ATTACHMENT:
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
case ResourceState::DEPTH_SAMPLER:
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) {
VkAccessFlags srcAccessMask, dstAccessMask; VkAccessFlags srcAccessMask, dstAccessMask;
VkPipelineStageFlags srcStage, dstStage; VkPipelineStageFlags srcStage, dstStage;
@ -96,8 +121,18 @@ namespace vkn {
dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break; break;
} }
mSrcStage |= srcStage;
return std::make_tuple(srcAccessMask, dstAccessMask, srcStage, dstStage, mDstStage |= dstStage;
getVkLayout(transition.oldLayout), getVkLayout(transition.newLayout)); return VkImageMemoryBarrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = srcAccessMask,
.dstAccessMask = dstAccessMask,
.oldLayout = GetVkLayout(barrier.mSrcState),
.newLayout = GetVkLayout(barrier.mDstState),
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = (VkImage)barrier.mTexture.image,
//.subresourceRange = transition.subresources,
};
} }
} }

View File

@ -4,6 +4,8 @@
#include "vkn/vulkan_api.h" #include "vkn/vulkan_api.h"
#include "vkn/backend.h" #include "vkn/backend.h"
#include "vkn/thread/command_worker.h" #include "vkn/thread/command_worker.h"
#include "render/asset/texture.h"
#include "asset/resource_system.h"
#include "zlog.h" #include "zlog.h"
#include <algorithm> #include <algorithm>
namespace vkn { namespace vkn {
@ -58,11 +60,16 @@ namespace vkn {
swapchain_images.resize(imageCount); swapchain_images.resize(imageCount);
vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data()); vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data());
mFences.reserve(mFrames); mFences.reserve(mFrames);
mSurfaces.reserve(mFrames);
mCommands.reserve(mFrames);
mSemaphores.reserve(mFrames + mFrames); mSemaphores.reserve(mFrames + mFrames);
for (int i = 0; i < mFrames; i++) { for (int i = 0; i < mFrames; i++) {
//mSurfaces.push_back(new Image(Creator.device, "swapchain" + to_string(i), swapchain_images[i], args)); api::TextureDesc desc;
desc.image = swapchain_images[i];
mSurfaces.push_back(desc);
mSemaphores.push_back(mDevice.CreateSemaphore()); mSemaphores.push_back(mDevice.CreateSemaphore());
mSemaphores.push_back(mDevice.CreateSemaphore()); mSemaphores.push_back(mDevice.CreateSemaphore());
mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT)); mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
} }
} }
@ -70,6 +77,8 @@ namespace vkn {
{ {
VkFence surfaceFence = mFences[ctx.frame]; VkFence surfaceFence = mFences[ctx.frame];
VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame]; VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame];
ctx.surface = mSurfaces[ctx.frame];
ctx.command = mCommands[ctx.frame];
ctx.surfaceSemaphore = surfaceSemaphore; ctx.surfaceSemaphore = surfaceSemaphore;
ctx.presentSemaphore = mSemaphores[ctx.frame + mFrames]; ctx.presentSemaphore = mSemaphores[ctx.frame + mFrames];
if (vkWaitForFences(mDevice.Ptr(), 1, &surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS) if (vkWaitForFences(mDevice.Ptr(), 1, &surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS)