Extra2D/src/renderer/render_graph.cpp

335 lines
8.5 KiB
C++
Raw Normal View History

#include <renderer/render_graph.h>
#include <renderer/rhi_module.h>
#include <utils/logger.h>
namespace extra2d {
// ========================================
// RenderPassContext 实现
// ========================================
TextureHandle
RenderPassContext::getTexture(RenderGraphResourceHandle handle) const {
if (graph) {
return graph->getTexture(handle);
}
return TextureHandle{};
}
// ========================================
// RenderGraphBuilder 实现
// ========================================
RenderGraphResourceHandle
RenderGraphBuilder::createTexture(const RenderGraphTextureDesc &desc) {
// 实际的资源创建由 RenderGraph 管理
// 这里只记录描述,返回临时句柄
textureDescs_.push_back(desc);
RenderGraphResourceHandle handle;
handle.index = static_cast<uint32_t>(textureDescs_.size()) - 1;
handle.type = RenderGraphResourceType::Texture;
return handle;
}
void RenderGraphBuilder::readResource(RenderGraphResourceHandle handle) {
// 记录资源读取依赖
// 用于后续的依赖分析和资源生命周期管理
}
void RenderGraphBuilder::writeResource(RenderGraphResourceHandle handle) {
// 记录资源写入依赖
}
void RenderGraphBuilder::setRenderTarget(
const RenderGraphRenderTargetDesc &desc) {
// 设置渲染目标
}
// ========================================
// RenderGraph 实现
// ========================================
RenderGraph::RenderGraph() = default;
RenderGraph::~RenderGraph() { shutdown(); }
RenderGraph::RenderGraph(RenderGraph &&other) noexcept
: passes_(std::move(other.passes_)),
executionOrder_(std::move(other.executionOrder_)),
textures_(std::move(other.textures_)),
nextResourceId_(other.nextResourceId_),
builder_(std::move(other.builder_)),
commandQueue_(std::move(other.commandQueue_)),
outputWidth_(other.outputWidth_), outputHeight_(other.outputHeight_),
frameIndex_(other.frameIndex_), compiled_(other.compiled_) {
other.nextResourceId_ = 1;
other.outputWidth_ = 1280;
other.outputHeight_ = 720;
other.frameIndex_ = 0;
other.compiled_ = false;
}
RenderGraph &RenderGraph::operator=(RenderGraph &&other) noexcept {
if (this != &other) {
shutdown();
passes_ = std::move(other.passes_);
executionOrder_ = std::move(other.executionOrder_);
textures_ = std::move(other.textures_);
nextResourceId_ = other.nextResourceId_;
builder_ = std::move(other.builder_);
commandQueue_ = std::move(other.commandQueue_);
outputWidth_ = other.outputWidth_;
outputHeight_ = other.outputHeight_;
frameIndex_ = other.frameIndex_;
compiled_ = other.compiled_;
other.nextResourceId_ = 1;
other.outputWidth_ = 1280;
other.outputHeight_ = 720;
other.frameIndex_ = 0;
other.compiled_ = false;
}
return *this;
}
bool RenderGraph::initialize() {
if (!commandQueue_.initialize()) {
E2D_LOG_ERROR("Failed to initialize CommandQueue");
return false;
}
E2D_LOG_INFO("RenderGraph initialized");
return true;
}
void RenderGraph::shutdown() {
destroyResources();
passes_.clear();
executionOrder_.clear();
commandQueue_.shutdown();
compiled_ = false;
E2D_LOG_INFO("RenderGraph shutdown");
}
RenderPass *RenderGraph::addPass(std::unique_ptr<RenderPass> pass) {
if (!pass)
return nullptr;
RenderPass *ptr = pass.get();
passes_.push_back(std::move(pass));
compiled_ = false; // 添加新通道需要重新编译
return ptr;
}
RenderPass *RenderGraph::addLambdaPass(
const std::string &name,
std::function<void(const RenderPassContext &)> executeFunc) {
// 创建一个简单的 lambda 渲染通道
class LambdaRenderPass : public RenderPass {
public:
std::string name;
std::function<void(const RenderPassContext &)> func;
LambdaRenderPass(const std::string &n,
std::function<void(const RenderPassContext &)> f)
: name(n), func(f) {}
const char *getName() const override { return name.c_str(); }
void execute(const RenderPassContext &ctx) override {
if (func) {
func(ctx);
}
}
};
return addPass(std::make_unique<LambdaRenderPass>(name, executeFunc));
}
bool RenderGraph::compile() {
if (compiled_)
return true;
// 清空之前的编译结果
executionOrder_.clear();
// 简单的编译策略:按添加顺序执行
// 实际实现中应该进行依赖分析和拓扑排序
for (auto &pass : passes_) {
if (pass->isEnabled()) {
executionOrder_.push_back(pass.get());
}
}
// 声明资源
for (auto *pass : executionOrder_) {
builder_.setCurrentPass(pass);
pass->declareResources(builder_);
}
// 创建资源
createResources();
compiled_ = true;
E2D_LOG_INFO("RenderGraph compiled with {} passes", executionOrder_.size());
return true;
}
void RenderGraph::execute(float deltaTime) {
if (!compiled_) {
if (!compile()) {
E2D_LOG_ERROR("Failed to compile RenderGraph");
return;
}
}
// 注意beginFrame 现在由 RendererModule::onRenderBegin 调用
// 这里不再调用,以避免清空已经提交的渲染命令
// 获取 RHI 上下文
auto *rhiModule = RHIModule::get();
RHIContext *context = nullptr;
if (rhiModule && rhiModule->getDevice()) {
context = rhiModule->getDevice()->getContext();
}
// 创建执行上下文
RenderPassContext ctx;
ctx.context = context;
ctx.commandQueue = &commandQueue_;
ctx.graph = this;
ctx.deltaTime = deltaTime;
ctx.frameIndex = frameIndex_;
// 执行所有通道
for (auto *pass : executionOrder_) {
if (pass->isEnabled()) {
pass->execute(ctx);
}
}
// 执行命令队列
// 执行命令队列
commandQueue_.execute();
// 结束帧
commandQueue_.endFrame();
// 调用 RHI 上下文的 endFrame 进行缓冲区交换
if (context) {
context->endFrame();
}
frameIndex_++;
}
TextureHandle RenderGraph::getTexture(RenderGraphResourceHandle handle) const {
auto it = textures_.find(handle.index);
if (it != textures_.end()) {
return it->second;
}
return TextureHandle{};
}
void RenderGraph::setOutputSize(uint32_t width, uint32_t height) {
outputWidth_ = width;
outputHeight_ = height;
}
void RenderGraph::createResources() {
auto *rhiModule = RHIModule::get();
if (!rhiModule || !rhiModule->getDevice())
return;
auto *device = rhiModule->getDevice();
// 创建渲染图内部资源
// 这里可以根据需要创建默认的后缓冲等
}
void RenderGraph::destroyResources() {
// 释放所有渲染图管理的资源
textures_.clear();
}
// ========================================
// GeometryRenderPass 实现
// ========================================
GeometryRenderPass::GeometryRenderPass(const std::string &name) : name_(name) {}
void GeometryRenderPass::declareResources(RenderGraphBuilder &builder) {
// 声明几何渲染通道的资源依赖
if (colorTarget_.isValid()) {
builder.writeResource(colorTarget_);
}
if (depthTarget_.isValid()) {
builder.writeResource(depthTarget_);
}
}
void GeometryRenderPass::execute(const RenderPassContext &ctx) {
// 几何渲染通道的执行逻辑
// 通常由外部的渲染系统填充具体的绘制命令
if (!ctx.commandQueue)
return;
// 清除颜色缓冲区
ctx.commandQueue->submitClear(Color::Black, CLEAR_COLOR_FLAG);
// 设置视口
if (ctx.graph) {
ctx.commandQueue->setViewport(
0, 0, static_cast<int32_t>(ctx.graph->getOutputWidth()),
static_cast<int32_t>(ctx.graph->getOutputHeight()));
}
}
// ========================================
// PostProcessRenderPass 实现
// ========================================
PostProcessRenderPass::PostProcessRenderPass(const std::string &name)
: name_(name) {}
void PostProcessRenderPass::declareResources(RenderGraphBuilder &builder) {
// 声明后期处理通道的资源依赖
if (inputTexture_.isValid()) {
builder.readResource(inputTexture_);
}
if (outputTarget_.isValid()) {
builder.writeResource(outputTarget_);
}
}
void PostProcessRenderPass::execute(const RenderPassContext &ctx) {
// 后期处理通道的执行逻辑
// 这里可以实现全屏四边形绘制等后期处理效果
if (!ctx.context || !ctx.commandQueue)
return;
// 获取命令列表
RHICommandList *cmdList = ctx.commandQueue->getCommandList();
if (!cmdList)
return;
// 绑定输入纹理
if (inputTexture_.isValid()) {
TextureHandle tex = ctx.getTexture(inputTexture_);
if (tex.isValid()) {
cmdList->setTexture(0, tex.get());
}
}
// 后期处理的具体实现由子类或外部提供
}
} // namespace extra2d