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()
{
graph.mSurface = context.surface;
for (auto view : context.views) {
RenderView(view);
}

View File

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

View File

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

View File

@ -8,8 +8,8 @@ namespace api {
class TextureBuilder;
class RenderPassBuilder;
public:
RscHandle<Texture> mSurface;
table<Name, RscHandle<Texture>> mResourceTable;
TextureDesc mSurface;
table<Name, TextureDesc> mResourceTable;
lemon::ListGraph mGraph;
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
public:
@ -23,7 +23,7 @@ namespace api {
void Compile();
void Execute(FRenderView& view);
void Clear();
RscHandle<Texture> Resource(Name name) {
TextureDesc Resource(Name name) {
auto it = mResourceTable.find(name);
if (it == mResourceTable.end()) {
return {};
@ -36,6 +36,6 @@ namespace api {
void ExecuteComputePass(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) {};
FrameGraph::RenderPassBuilder& Name(pmr::Name name);
FrameGraph::RenderPassBuilder& Pass(RenderPass* pass);
FrameGraph::RenderPassBuilder& Read(TextureDesc desc);
FrameGraph::RenderPassBuilder& Write(TextureDesc desc);
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc);
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);
};
struct FrameGraph::TextureBuilder {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,26 +3,11 @@
namespace api {
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
{
auto edge = graph.CreateTexture(
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) {
builder.Name("import")
.Import(graph.Resource("demo_input"));
});
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) {
});
AttachmentDesc surface{};
surface.image = graph.mSurface.image;
surface.colorFormat = TinyImageFormat_B8G8R8_UNORM;
builder.Name("MiniPass")
.Attach(surface, ResourceState::PRESENT);
}
void DemoPass::Execute(FrameGraph&, RenderPassContext&)
{

View File

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

View File

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

View File

@ -1,4 +1,15 @@
#include "type.h"
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 {
class Device;
struct VulkanContext;
using api::TextureDesc;
struct VULKAN_API VulkanWindowArgs {
uint32_t frames;
uint32_t width;
@ -22,7 +23,8 @@ namespace vkn {
Device& mDevice;
VkSwapchainKHR mPtr;
int mFrames;
//pmr::vector<Image*> mSurfaces{GlobalPool()};
pmr::vector<TextureDesc> mSurfaces{GlobalPool()};
pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() };
pmr::vector<VkFence> mFences{ GlobalPool() };
pmr::vector<VkSemaphore> mSemaphores{ GlobalPool() };
public:

View File

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

View File

@ -1,10 +1,35 @@
#include <tuple>
#include "vkn/vulkan_api_help.h"
namespace vkn {
using api::ResourceState;
inline std::tuple<VkAccessFlags, VkAccessFlags, VkPipelineStageFlags, VkPipelineStageFlags,
VkImageLayout, VkImageLayout>
getVkTransition(const api::TextureBarrier& barrier) {
VkImageLayout GetVkLayout(ResourceState layout) {
switch (layout) {
case ResourceState::UNDEFINED:
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;
VkPipelineStageFlags srcStage, dstStage;
@ -96,8 +121,18 @@ namespace vkn {
dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
}
return std::make_tuple(srcAccessMask, dstAccessMask, srcStage, dstStage,
getVkLayout(transition.oldLayout), getVkLayout(transition.newLayout));
mSrcStage |= srcStage;
mDstStage |= dstStage;
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/backend.h"
#include "vkn/thread/command_worker.h"
#include "render/asset/texture.h"
#include "asset/resource_system.h"
#include "zlog.h"
#include <algorithm>
namespace vkn {
@ -58,11 +60,16 @@ namespace vkn {
swapchain_images.resize(imageCount);
vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data());
mFences.reserve(mFrames);
mSurfaces.reserve(mFrames);
mCommands.reserve(mFrames);
mSemaphores.reserve(mFrames + mFrames);
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());
mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
}
}
@ -70,6 +77,8 @@ namespace vkn {
{
VkFence surfaceFence = mFences[ctx.frame];
VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame];
ctx.surface = mSurfaces[ctx.frame];
ctx.command = mCommands[ctx.frame];
ctx.surfaceSemaphore = surfaceSemaphore;
ctx.presentSemaphore = mSemaphores[ctx.frame + mFrames];
if (vkWaitForFences(mDevice.Ptr(), 1, &surfaceFence, VK_TRUE, UINT64_MAX) != VK_SUCCESS)