update framegraph
This commit is contained in:
parent
4c0291d271
commit
f89424979e
@ -7,15 +7,15 @@ namespace api {
|
|||||||
class TextureBuilder;
|
class TextureBuilder;
|
||||||
class RenderPassBuilder;
|
class RenderPassBuilder;
|
||||||
public:
|
public:
|
||||||
lemon::ListGraph mGraph;
|
lemon::ListGraph mGraph;
|
||||||
pmr::vector<RenderPassNode*> mPasses{FramePool()};
|
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
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&)>;
|
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&)>;
|
using TextureSetupFunction = std::function<void(FrameGraph&, class TextureBuilder&)>;
|
||||||
FrameResourceEdge* CreateTexture(const TextureSetupFunction& setup);
|
FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup);
|
||||||
|
|
||||||
void Compile();
|
void Compile();
|
||||||
void Execute();
|
void Execute();
|
||||||
|
|||||||
@ -3,22 +3,23 @@
|
|||||||
namespace api {
|
namespace api {
|
||||||
struct FrameGraph::RenderPassBuilder {
|
struct FrameGraph::RenderPassBuilder {
|
||||||
FrameGraph& graph;
|
FrameGraph& graph;
|
||||||
RenderPassNode& node;
|
FrameGraphNodePtr& node;
|
||||||
FrameResourceEdge* edge;
|
FrameResource* resource;
|
||||||
public:
|
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& Name(pmr::Name name);
|
||||||
FrameGraph::RenderPassBuilder& Pass(RenderPass* pass);
|
FrameGraph::RenderPassBuilder& Pass(RenderPass* pass);
|
||||||
FrameGraph::RenderPassBuilder& Read(TextureDesc desc);
|
FrameGraph::RenderPassBuilder& Read(TextureDesc desc);
|
||||||
FrameGraph::RenderPassBuilder& Write(TextureDesc desc);
|
FrameGraph::RenderPassBuilder& Write(TextureDesc desc);
|
||||||
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc);
|
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc);
|
||||||
FrameGraph::RenderPassBuilder& Read(FrameResourceEdge* edge);
|
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& edge);
|
||||||
};
|
};
|
||||||
struct FrameGraph::TextureBuilder {
|
struct FrameGraph::TextureBuilder {
|
||||||
FrameGraph& graph;
|
FrameGraph& graph;
|
||||||
FrameResourceEdge& edge;
|
FrameGraphEdgePtr& edge;
|
||||||
public:
|
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& Name(pmr::Name name);
|
||||||
FrameGraph::TextureBuilder& Import(RscHandle<Texture> handle);
|
FrameGraph::TextureBuilder& Import(RscHandle<Texture> handle);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,40 +13,78 @@ namespace api {
|
|||||||
using RenderPassExecuteFunction = std::function<void(FrameGraph&, RenderPassContext&)>;
|
using RenderPassExecuteFunction = std::function<void(FrameGraph&, RenderPassContext&)>;
|
||||||
using RenderPassNodeExecuteFn = std::variant<RenderPassExecuteFunction, ComputePassExecuteFunction, CopyPassExecuteFunction>;
|
using RenderPassNodeExecuteFn = std::variant<RenderPassExecuteFunction, ComputePassExecuteFunction, CopyPassExecuteFunction>;
|
||||||
class RenderPass;
|
class RenderPass;
|
||||||
class FrameResourceEdge;
|
class RenderPassNode;
|
||||||
enum class ERenderPassNodeType : uint8_t {
|
struct FrameGraphNodePtr {
|
||||||
Render,
|
enum NodeType : uint8_t {
|
||||||
Present,
|
Render,
|
||||||
Compute,
|
Present,
|
||||||
Copy
|
Compute,
|
||||||
};
|
Copy
|
||||||
struct RenderPassNode {
|
};
|
||||||
using GraphNodeRef = lemon::ListGraphBase::Node;
|
using GraphNodeRef = lemon::ListGraphBase::Node;
|
||||||
GraphNodeRef ref;
|
GraphNodeRef ref;
|
||||||
Name name;
|
NodeType type{ NodeType::Render };
|
||||||
ERenderPassNodeType type{ ERenderPassNodeType::Render};
|
RenderPassNode* node;
|
||||||
RenderPass* pass;
|
FrameGraphNodePtr() : node(nullptr){};
|
||||||
RenderPassNodeExecuteFn executor;
|
FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
|
||||||
pmr::vector<FrameResourceEdge*> edges{ FramePool() };//read -> write, 顺序固定
|
operator bool() const {
|
||||||
RenderPassNode(GraphNodeRef ref) : ref(ref) {}
|
return node;
|
||||||
FrameResourceEdge* GetInput(int i);
|
}
|
||||||
FrameResourceEdge* GetOutput(int i);
|
RenderPassNode* operator ->()const {
|
||||||
FrameResourceEdge* FindInput(Name name);
|
return node;
|
||||||
FrameResourceEdge* FindOutput(Name name);
|
}
|
||||||
};
|
};
|
||||||
struct FrameTextureResource {
|
struct FrameTextureResource {
|
||||||
TextureDesc texture;
|
TextureDesc texture;
|
||||||
AttachmentDesc attach;
|
AttachmentDesc attach;
|
||||||
};
|
};
|
||||||
struct FrameResourceEdge {
|
struct FrameResource {
|
||||||
using Resource = std::variant<FrameTextureResource, void*>;
|
using Resource = std::variant<FrameTextureResource, void*>;
|
||||||
Name name;
|
Name name;
|
||||||
Resource resource;
|
Resource resource;
|
||||||
RenderPassNode* source;
|
FrameGraphNodePtr source;
|
||||||
pmr::vector<RenderPassNode*> targets{ FramePool() };
|
pmr::vector<FrameGraphNodePtr> targets{ FramePool() };
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T CastTo() {
|
T CastTo() {
|
||||||
return std::get<T>(resource);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,46 +1,47 @@
|
|||||||
#include "render/graph/frame_graph.h"
|
#include "render/graph/frame_graph.h"
|
||||||
#include "render/graph/frame_graph_builder.h"
|
#include "render/graph/frame_graph_builder.h"
|
||||||
namespace api {
|
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());
|
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor };
|
||||||
RenderPassBuilder builder{this, node};
|
RenderPassBuilder builder{ this, node_ptr };
|
||||||
setup(*this, builder);
|
setup(*this, builder);
|
||||||
node->executor = executor;
|
mNodes.push_back(node_ptr);
|
||||||
mPasses.push_back(node);
|
return node_ptr;
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
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;
|
return edge;
|
||||||
}
|
}
|
||||||
void FrameGraph::Compile()
|
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;
|
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;
|
++degree;
|
||||||
}
|
}
|
||||||
return degree;
|
return !degree;
|
||||||
});
|
});
|
||||||
mPasses.erase(end, mPasses.end());
|
mNodes.erase(end, mNodes.end());
|
||||||
}
|
}
|
||||||
void FrameGraph::Execute()
|
void FrameGraph::Execute()
|
||||||
{
|
{
|
||||||
for (auto pass : mPasses) {
|
for (auto node : mNodes) {
|
||||||
switch (pass->type) {
|
switch (node.type) {
|
||||||
case ERenderPassNodeType::Render:
|
case FrameGraphNodePtr::Render:
|
||||||
ExecuteRenderPass(pass);
|
ExecuteRenderPass(node.node);
|
||||||
break;
|
break;
|
||||||
case ERenderPassNodeType::Present:
|
case FrameGraphNodePtr::Present:
|
||||||
ExecuteComputePass(pass);
|
ExecuteComputePass(node.node);
|
||||||
break;
|
break;
|
||||||
case ERenderPassNodeType::Compute:
|
case FrameGraphNodePtr::Compute:
|
||||||
ExecuteRenderPass(pass);
|
ExecuteRenderPass(node.node);
|
||||||
break;
|
break;
|
||||||
case ERenderPassNodeType::Copy:
|
case FrameGraphNodePtr::Copy:
|
||||||
ExecuteCopyPass(pass);
|
ExecuteCopyPass(node.node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ namespace api {
|
|||||||
void FrameGraph::Clear()
|
void FrameGraph::Clear()
|
||||||
{
|
{
|
||||||
mGraph.clear();
|
mGraph.clear();
|
||||||
mPasses.clear();
|
mNodes.clear();
|
||||||
}
|
}
|
||||||
void FrameGraph::ExecuteRenderPass(RenderPassNode* node)
|
void FrameGraph::ExecuteRenderPass(RenderPassNode* node)
|
||||||
{
|
{
|
||||||
@ -70,39 +71,39 @@ namespace api {
|
|||||||
CopyPassContext context{};
|
CopyPassContext context{};
|
||||||
std::get<CopyPassExecuteFunction>(node->executor)(*this, context);
|
std::get<CopyPassExecuteFunction>(node->executor)(*this, context);
|
||||||
}
|
}
|
||||||
FrameResourceEdge* RenderPassNode::GetInput(int i)
|
FrameGraphEdgePtr RenderPassNode::GetInput(int i)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (auto edge : edges) {
|
for (auto edge : edges) {
|
||||||
if (edge->source == this && count++ == i) {
|
if (edge.type != FrameGraphEdgePtr::Output && count++ == i) {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FrameResourceEdge* RenderPassNode::GetOutput(int i)
|
FrameGraphEdgePtr RenderPassNode::GetOutput(int i)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (auto edge : edges) {
|
for (auto edge : edges) {
|
||||||
if (edge->source && edge->source != this && count++ == i) {
|
if (edge.type == FrameGraphEdgePtr::Output && count++ == i) {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FrameResourceEdge* RenderPassNode::FindInput(Name name)
|
FrameGraphEdgePtr RenderPassNode::FindInput(Name name)
|
||||||
{
|
{
|
||||||
for (auto edge : edges) {
|
for (auto edge : edges) {
|
||||||
if (edge->name == name && edge->source == this) {
|
if (edge.resource->name == name && edge.type != FrameGraphEdgePtr::Output) {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
FrameResourceEdge* RenderPassNode::FindOutput(Name name)
|
FrameGraphEdgePtr RenderPassNode::FindOutput(Name name)
|
||||||
{
|
{
|
||||||
for (auto edge : edges) {
|
for (auto edge : edges) {
|
||||||
if (edge->name == name && edge->source && edge->source != this) {
|
if (edge.resource->name == name && edge.type == FrameGraphEdgePtr::Output) {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,56 +3,61 @@
|
|||||||
namespace api {
|
namespace api {
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
|
||||||
{
|
{
|
||||||
node.name = name;
|
node->name = name;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Pass(RenderPass* pass)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Pass(RenderPass* pass)
|
||||||
{
|
{
|
||||||
node.pass = pass;
|
node->pass = pass;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc)
|
||||||
{
|
{
|
||||||
edge = new(FramePool()) FrameResourceEdge();
|
FrameGraphEdgePtr edge{ FrameGraphEdgePtr::Input };
|
||||||
edge->source = &node;
|
resource = edge.resource;
|
||||||
edge->resource = FrameTextureResource{desc};
|
resource->source = node;
|
||||||
node.edges.push_back(edge);
|
resource->resource = FrameTextureResource{desc};
|
||||||
|
node->edges.push_back(edge);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(TextureDesc desc)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(TextureDesc desc)
|
||||||
{
|
{
|
||||||
edge = new(FramePool()) FrameResourceEdge();
|
FrameGraphEdgePtr edge{ FrameGraphEdgePtr::Output };
|
||||||
edge->source = &node;
|
resource = edge.resource;
|
||||||
edge->resource = FrameTextureResource{ desc };
|
resource->source = node;
|
||||||
node.edges.push_back(edge);
|
resource->resource = FrameTextureResource{ desc };
|
||||||
|
node->edges.push_back(edge);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc)
|
||||||
{
|
{
|
||||||
if (edge) {
|
if (resource) {
|
||||||
auto& resource = std::get<FrameTextureResource>(edge->resource);
|
auto& text_resource = std::get<FrameTextureResource>(resource->resource);
|
||||||
resource.attach = desc;
|
text_resource.attach = desc;
|
||||||
}
|
}
|
||||||
return *this;
|
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)
|
if(edge->source)
|
||||||
graph.mGraph.addEdge(edge->source->ref, node.ref);
|
graph.mGraph.addEdge(edge->source.ref, node.ref);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Name(pmr::Name name)
|
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Name(pmr::Name name)
|
||||||
{
|
{
|
||||||
edge.name = name;
|
edge->name = name;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(RscHandle<Texture> handle)
|
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(RscHandle<Texture> handle)
|
||||||
{
|
{
|
||||||
|
edge.type = FrameGraphEdgePtr::Import;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,20 +4,21 @@ namespace api {
|
|||||||
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
||||||
{
|
{
|
||||||
auto edge = graph.CreateTexture(
|
auto edge = graph.CreateTexture(
|
||||||
[=](auto&, auto) {
|
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) {
|
||||||
|
builder.Name("import")
|
||||||
|
.Import({});
|
||||||
});
|
});
|
||||||
builder.Name("DemoPass")
|
builder.Name("DemoPass")
|
||||||
.Read(TextureDesc::Make())
|
.Read(TextureDesc::Make())
|
||||||
.Read(edge)
|
.Read(edge)
|
||||||
.Write(TextureDesc::Make())
|
.Write(TextureDesc::Make())
|
||||||
.Attach(AttachmentDesc::Make());
|
.Attach(AttachmentDesc::Make());
|
||||||
auto parent_pass = &builder.node;
|
auto parent_node = builder.node;
|
||||||
graph.AddRenderPass(
|
graph.AddRenderPass(
|
||||||
[=](FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) {
|
[=](FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) {
|
||||||
builder.Name("DemoPassSub")
|
builder.Name("DemoPassSub")
|
||||||
.Read(edge)
|
.Read(edge)
|
||||||
.Read(parent_pass->GetOutput(0));
|
.Read(parent_node->GetOutput(0));
|
||||||
},
|
},
|
||||||
[](FrameGraph& graph, RenderPassContext& context) {
|
[](FrameGraph& graph, RenderPassContext& context) {
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user