update framegraph

This commit is contained in:
ouczbs 2024-08-10 18:02:39 +08:00
parent 4c0291d271
commit f89424979e
6 changed files with 130 additions and 84 deletions

View File

@ -7,15 +7,15 @@ namespace api {
class TextureBuilder;
class RenderPassBuilder;
public:
lemon::ListGraph mGraph;
pmr::vector<RenderPassNode*> mPasses{FramePool()};
lemon::ListGraph mGraph;
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
public:
template<typename T>
RenderPassNode* AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); }
FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); }
using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>;
RenderPassNode* AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
using TextureSetupFunction = std::function<void(FrameGraph&, class TextureBuilder&)>;
FrameResourceEdge* CreateTexture(const TextureSetupFunction& setup);
FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup);
void Compile();
void Execute();

View File

@ -3,22 +3,23 @@
namespace api {
struct FrameGraph::RenderPassBuilder {
FrameGraph& graph;
RenderPassNode& node;
FrameResourceEdge* edge;
FrameGraphNodePtr& node;
FrameResource* resource;
public:
RenderPassBuilder(FrameGraph* graph, RenderPassNode* node) noexcept: graph(*graph) , node(*node) {};
RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept
: 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(FrameResourceEdge* edge);
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& edge);
};
struct FrameGraph::TextureBuilder {
FrameGraph& graph;
FrameResourceEdge& edge;
FrameGraphEdgePtr& edge;
public:
TextureBuilder(FrameGraph* graph, FrameResourceEdge* edge)noexcept : graph(*graph), edge(*edge) {};
TextureBuilder(FrameGraph* graph, FrameGraphEdgePtr& edge)noexcept : graph(*graph), edge(edge) {};
FrameGraph::TextureBuilder& Name(pmr::Name name);
FrameGraph::TextureBuilder& Import(RscHandle<Texture> handle);
};

View File

@ -13,40 +13,78 @@ namespace api {
using RenderPassExecuteFunction = std::function<void(FrameGraph&, RenderPassContext&)>;
using RenderPassNodeExecuteFn = std::variant<RenderPassExecuteFunction, ComputePassExecuteFunction, CopyPassExecuteFunction>;
class RenderPass;
class FrameResourceEdge;
enum class ERenderPassNodeType : uint8_t {
Render,
Present,
Compute,
Copy
};
struct RenderPassNode {
class RenderPassNode;
struct FrameGraphNodePtr {
enum NodeType : uint8_t {
Render,
Present,
Compute,
Copy
};
using GraphNodeRef = lemon::ListGraphBase::Node;
GraphNodeRef ref;
Name name;
ERenderPassNodeType type{ ERenderPassNodeType::Render};
RenderPass* pass;
RenderPassNodeExecuteFn executor;
pmr::vector<FrameResourceEdge*> edges{ FramePool() };//read -> write, 顺序固定
RenderPassNode(GraphNodeRef ref) : ref(ref) {}
FrameResourceEdge* GetInput(int i);
FrameResourceEdge* GetOutput(int i);
FrameResourceEdge* FindInput(Name name);
FrameResourceEdge* FindOutput(Name name);
NodeType type{ NodeType::Render };
RenderPassNode* node;
FrameGraphNodePtr() : node(nullptr){};
FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
operator bool() const {
return node;
}
RenderPassNode* operator ->()const {
return node;
}
};
struct FrameTextureResource {
TextureDesc texture;
AttachmentDesc attach;
};
struct FrameResourceEdge {
struct FrameResource {
using Resource = std::variant<FrameTextureResource, void*>;
Name name;
Resource resource;
RenderPassNode* source;
pmr::vector<RenderPassNode*> targets{ FramePool() };
FrameGraphNodePtr source;
pmr::vector<FrameGraphNodePtr> targets{ FramePool() };
template<typename T>
T CastTo() {
return std::get<T>(resource);
}
};
struct FrameGraphEdgePtr {
enum EdgeType : uint8_t {
Import,
Input,
Output
};
EdgeType type{ EdgeType::Import };
FrameResource* resource;
FrameGraphEdgePtr() : resource(nullptr) {};
FrameGraphEdgePtr(FrameResource* resource, EdgeType type = EdgeType::Import)
: resource(resource), type(type) {}
FrameGraphEdgePtr(EdgeType type) : type(type){
resource = new (FramePool()) FrameResource();
}
bool IsImport() const { return type == EdgeType::Import; }
operator bool() const{
return resource;
}
FrameResource* operator ->()const {
return resource;
}
};
struct RenderPassNode {
Name name;
RenderPass* pass;
RenderPassNodeExecuteFn executor;
pmr::vector<FrameGraphEdgePtr> edges{ FramePool() };//read -> write, 顺序固定
FrameGraphEdgePtr GetInput(int i);
FrameGraphEdgePtr GetOutput(int i);
FrameGraphEdgePtr FindInput(Name name);
FrameGraphEdgePtr FindOutput(Name name);
};
inline FrameGraphNodePtr::FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type)
: ref(ref), type(type)
{
node = new (FramePool()) RenderPassNode();
node->executor = executor;
}
}

View File

@ -1,46 +1,47 @@
#include "render/graph/frame_graph.h"
#include "render/graph/frame_graph_builder.h"
namespace api {
RenderPassNode* FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
{
RenderPassNode* node = new(FramePool()) RenderPassNode(mGraph.addNode());
RenderPassBuilder builder{this, node};
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor };
RenderPassBuilder builder{ this, node_ptr };
setup(*this, builder);
node->executor = executor;
mPasses.push_back(node);
return node;
mNodes.push_back(node_ptr);
return node_ptr;
}
FrameResourceEdge* FrameGraph::CreateTexture(const TextureSetupFunction& setup)
FrameGraphEdgePtr FrameGraph::CreateTexture(const TextureSetupFunction& setup)
{
FrameResourceEdge* edge = new(FramePool()) FrameResourceEdge();
FrameGraphEdgePtr edge{ FrameGraphEdgePtr::Import };
TextureBuilder builder(this, edge);
setup(*this, builder);
return edge;
}
void FrameGraph::Compile()
{
auto end = std::remove_if(mPasses.begin(), mPasses.end(), [this](RenderPassNode* pass) {
auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) {
int degree = 0;
for (lemon::ListGraph::IncEdgeIt e(mGraph, pass->ref); e != lemon::INVALID; ++e) {
for (lemon::ListGraph::IncEdgeIt e(mGraph, node.ref); e != lemon::INVALID; ++e) {
++degree;
}
return degree;
return !degree;
});
mPasses.erase(end, mPasses.end());
mNodes.erase(end, mNodes.end());
}
void FrameGraph::Execute()
{
for (auto pass : mPasses) {
switch (pass->type) {
case ERenderPassNodeType::Render:
ExecuteRenderPass(pass);
for (auto node : mNodes) {
switch (node.type) {
case FrameGraphNodePtr::Render:
ExecuteRenderPass(node.node);
break;
case ERenderPassNodeType::Present:
ExecuteComputePass(pass);
case FrameGraphNodePtr::Present:
ExecuteComputePass(node.node);
break;
case ERenderPassNodeType::Compute:
ExecuteRenderPass(pass);
case FrameGraphNodePtr::Compute:
ExecuteRenderPass(node.node);
break;
case ERenderPassNodeType::Copy:
ExecuteCopyPass(pass);
case FrameGraphNodePtr::Copy:
ExecuteCopyPass(node.node);
break;
}
}
@ -48,7 +49,7 @@ namespace api {
void FrameGraph::Clear()
{
mGraph.clear();
mPasses.clear();
mNodes.clear();
}
void FrameGraph::ExecuteRenderPass(RenderPassNode* node)
{
@ -70,39 +71,39 @@ namespace api {
CopyPassContext context{};
std::get<CopyPassExecuteFunction>(node->executor)(*this, context);
}
FrameResourceEdge* RenderPassNode::GetInput(int i)
FrameGraphEdgePtr RenderPassNode::GetInput(int i)
{
int count = 0;
for (auto edge : edges) {
if (edge->source == this && count++ == i) {
if (edge.type != FrameGraphEdgePtr::Output && count++ == i) {
return edge;
}
}
return nullptr;
}
FrameResourceEdge* RenderPassNode::GetOutput(int i)
FrameGraphEdgePtr RenderPassNode::GetOutput(int i)
{
int count = 0;
for (auto edge : edges) {
if (edge->source && edge->source != this && count++ == i) {
if (edge.type == FrameGraphEdgePtr::Output && count++ == i) {
return edge;
}
}
return nullptr;
}
FrameResourceEdge* RenderPassNode::FindInput(Name name)
FrameGraphEdgePtr RenderPassNode::FindInput(Name name)
{
for (auto edge : edges) {
if (edge->name == name && edge->source == this) {
if (edge.resource->name == name && edge.type != FrameGraphEdgePtr::Output) {
return edge;
}
}
return nullptr;
}
FrameResourceEdge* RenderPassNode::FindOutput(Name name)
FrameGraphEdgePtr RenderPassNode::FindOutput(Name name)
{
for (auto edge : edges) {
if (edge->name == name && edge->source && edge->source != this) {
if (edge.resource->name == name && edge.type == FrameGraphEdgePtr::Output) {
return edge;
}
}

View File

@ -3,56 +3,61 @@
namespace api {
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
{
node.name = name;
node->name = name;
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Pass(RenderPass* pass)
{
node.pass = pass;
node->pass = pass;
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc)
{
edge = new(FramePool()) FrameResourceEdge();
edge->source = &node;
edge->resource = FrameTextureResource{desc};
node.edges.push_back(edge);
FrameGraphEdgePtr edge{ FrameGraphEdgePtr::Input };
resource = edge.resource;
resource->source = node;
resource->resource = FrameTextureResource{desc};
node->edges.push_back(edge);
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(TextureDesc desc)
{
edge = new(FramePool()) FrameResourceEdge();
edge->source = &node;
edge->resource = FrameTextureResource{ desc };
node.edges.push_back(edge);
FrameGraphEdgePtr edge{ FrameGraphEdgePtr::Output };
resource = edge.resource;
resource->source = node;
resource->resource = FrameTextureResource{ desc };
node->edges.push_back(edge);
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc)
{
if (edge) {
auto& resource = std::get<FrameTextureResource>(edge->resource);
resource.attach = desc;
if (resource) {
auto& text_resource = std::get<FrameTextureResource>(resource->resource);
text_resource.attach = desc;
}
return *this;
}
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(FrameResourceEdge* edge)
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& edge)
{
edge->targets.emplace_back(&node);
if (!edge) { return *this; }
node->edges.emplace_back(edge.resource, edge.IsImport() ? FrameGraphEdgePtr::Import : FrameGraphEdgePtr::Input);
edge->targets.emplace_back(node);
if(edge->source)
graph.mGraph.addEdge(edge->source->ref, node.ref);
graph.mGraph.addEdge(edge->source.ref, node.ref);
return *this;
}
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Name(pmr::Name name)
{
edge.name = name;
edge->name = name;
return *this;
}
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(RscHandle<Texture> handle)
{
edge.type = FrameGraphEdgePtr::Import;
return *this;
}
}

View File

@ -4,20 +4,21 @@ namespace api {
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
{
auto edge = graph.CreateTexture(
[=](auto&, auto) {
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) {
builder.Name("import")
.Import({});
});
builder.Name("DemoPass")
.Read(TextureDesc::Make())
.Read(edge)
.Write(TextureDesc::Make())
.Attach(AttachmentDesc::Make());
auto parent_pass = &builder.node;
auto parent_node = builder.node;
graph.AddRenderPass(
[=](FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) {
builder.Name("DemoPassSub")
.Read(edge)
.Read(parent_pass->GetOutput(0));
.Read(parent_node->GetOutput(0));
},
[](FrameGraph& graph, RenderPassContext& context) {