Extra2D/include/renderer/render_graph.h

366 lines
8.3 KiB
C++

#pragma once
#include <renderer/rhi/rhi.h>
#include <renderer/command_queue.h>
#include <types/math/color.h>
#include <types/math/rect.h>
#include <string>
#include <vector>
#include <functional>
#include <memory>
#include <unordered_map>
namespace extra2d {
// 前向声明
class RenderGraph;
class RenderPass;
class RenderGraphBuilder;
/**
* @brief 渲染图资源类型
*/
enum class RenderGraphResourceType : uint8_t {
Texture, // 纹理
Buffer, // 缓冲区
RenderTarget // 渲染目标
};
/**
* @brief 渲染图资源句柄
*/
struct RenderGraphResourceHandle {
uint32_t index = static_cast<uint32_t>(-1);
RenderGraphResourceType type = RenderGraphResourceType::Texture;
bool isValid() const { return index != static_cast<uint32_t>(-1); }
static RenderGraphResourceHandle invalid() { return RenderGraphResourceHandle{}; }
};
/**
* @brief 纹理描述
*/
struct RenderGraphTextureDesc {
uint32_t width = 0;
uint32_t height = 0;
TextureFormat format = TextureFormat::RGBA8;
TextureUsage usage = TextureUsage::Sampled;
bool isRenderTarget = false;
std::string name;
static RenderGraphTextureDesc create2D(uint32_t w, uint32_t h, TextureFormat fmt,
const std::string& name = "") {
RenderGraphTextureDesc desc;
desc.width = w;
desc.height = h;
desc.format = fmt;
desc.name = name;
return desc;
}
};
/**
* @brief 渲染目标描述
*/
struct RenderGraphRenderTargetDesc {
RenderGraphResourceHandle colorTarget;
RenderGraphResourceHandle depthTarget;
Rect clearRect;
Color clearColor = Color::Black;
float clearDepth = 1.0f;
uint8_t clearStencil = 0;
bool clearColorFlag = true;
bool clearDepthFlag = false;
bool clearStencilFlag = false;
};
/**
* @brief 渲染通道类型
*/
enum class RenderPassType : uint8_t {
Graphics, // 图形渲染
Compute, // 计算
Copy // 拷贝/传输
};
/**
* @brief 渲染通道执行上下文
*/
struct RenderPassContext {
RHIContext* context = nullptr;
CommandQueue* commandQueue = nullptr;
RenderGraph* graph = nullptr;
float deltaTime = 0.0f;
uint32_t frameIndex = 0;
// 获取纹理句柄
TextureHandle getTexture(RenderGraphResourceHandle handle) const;
};
/**
* @brief 渲染通道基类
*/
class RenderPass {
public:
virtual ~RenderPass() = default;
/**
* @brief 获取通道名称
*/
virtual const char* getName() const = 0;
/**
* @brief 获取通道类型
*/
virtual RenderPassType getType() const { return RenderPassType::Graphics; }
/**
* @brief 声明资源依赖
* @param builder 渲染图构建器
*/
virtual void declareResources(RenderGraphBuilder& builder) {}
/**
* @brief 执行渲染通道
* @param ctx 执行上下文
*/
virtual void execute(const RenderPassContext& ctx) = 0;
/**
* @brief 设置是否启用
*/
void setEnabled(bool enabled) { enabled_ = enabled; }
/**
* @brief 检查是否启用
*/
bool isEnabled() const { return enabled_; }
private:
bool enabled_ = true;
};
/**
* @brief 渲染图构建器
*
* 用于声明渲染通道的资源依赖
*/
class RenderGraphBuilder {
public:
/**
* @brief 创建纹理
* @param desc 纹理描述
* @return 资源句柄
*/
RenderGraphResourceHandle createTexture(const RenderGraphTextureDesc& desc);
/**
* @brief 读取资源
* @param handle 资源句柄
*/
void readResource(RenderGraphResourceHandle handle);
/**
* @brief 写入资源
* @param handle 资源句柄
*/
void writeResource(RenderGraphResourceHandle handle);
/**
* @brief 设置渲染目标
* @param desc 渲染目标描述
*/
void setRenderTarget(const RenderGraphRenderTargetDesc& desc);
// 内部使用
void setCurrentPass(RenderPass* pass) { currentPass_ = pass; }
private:
RenderPass* currentPass_ = nullptr;
std::vector<RenderGraphTextureDesc> textureDescs_;
};
/**
* @brief 渲染图
*
* 管理渲染通道的依赖关系和执行顺序
* 提供声明式渲染流程定义
*/
class RenderGraph {
public:
RenderGraph();
~RenderGraph();
// 禁止拷贝
RenderGraph(const RenderGraph&) = delete;
RenderGraph& operator=(const RenderGraph&) = delete;
// 允许移动
RenderGraph(RenderGraph&&) noexcept;
RenderGraph& operator=(RenderGraph&&) noexcept;
/**
* @brief 初始化渲染图
* @return 初始化是否成功
*/
bool initialize();
/**
* @brief 关闭渲染图
*/
void shutdown();
/**
* @brief 添加渲染通道
* @param pass 渲染通道(所有权转移)
* @return 渲染通道指针
*/
RenderPass* addPass(std::unique_ptr<RenderPass> pass);
/**
* @brief 创建渲染通道(便捷方法)
* @param name 通道名称
* @param executeFunc 执行函数
* @return 渲染通道指针
*/
RenderPass* addLambdaPass(const std::string& name,
std::function<void(const RenderPassContext&)> executeFunc);
/**
* @brief 编译渲染图
*
* 分析依赖关系,确定执行顺序,分配资源
*/
bool compile();
/**
* @brief 执行渲染图
* @param deltaTime 帧时间
*/
void execute(float deltaTime);
/**
* @brief 获取纹理资源
* @param handle 资源句柄
* @return 纹理句柄
*/
TextureHandle getTexture(RenderGraphResourceHandle handle) const;
/**
* @brief 设置输出尺寸
* @param width 宽度
* @param height 高度
*/
void setOutputSize(uint32_t width, uint32_t height);
/**
* @brief 获取输出宽度
*/
uint32_t getOutputWidth() const { return outputWidth_; }
/**
* @brief 获取输出高度
*/
uint32_t getOutputHeight() const { return outputHeight_; }
/**
* @brief 获取命令队列
*/
CommandQueue* getCommandQueue() { return &commandQueue_; }
private:
// 渲染通道列表
std::vector<std::unique_ptr<RenderPass>> passes_;
// 编译后的执行顺序
std::vector<RenderPass*> executionOrder_;
// 资源管理
std::unordered_map<uint32_t, TextureHandle> textures_;
uint32_t nextResourceId_ = 1;
// 构建器
RenderGraphBuilder builder_;
// 命令队列
CommandQueue commandQueue_;
// 输出尺寸
uint32_t outputWidth_ = 1280;
uint32_t outputHeight_ = 720;
// 帧计数
uint32_t frameIndex_ = 0;
// 编译状态
bool compiled_ = false;
/**
* @brief 创建内部资源
*/
void createResources();
/**
* @brief 销毁内部资源
*/
void destroyResources();
};
/**
* @brief 简单的几何渲染通道
*
* 用于常规的 2D 几何渲染
*/
class GeometryRenderPass : public RenderPass {
public:
GeometryRenderPass(const std::string& name);
const char* getName() const override { return name_.c_str(); }
void declareResources(RenderGraphBuilder& builder) override;
void execute(const RenderPassContext& ctx) override;
/**
* @brief 设置颜色目标
*/
void setColorTarget(RenderGraphResourceHandle handle) { colorTarget_ = handle; }
/**
* @brief 设置深度目标
*/
void setDepthTarget(RenderGraphResourceHandle handle) { depthTarget_ = handle; }
private:
std::string name_;
RenderGraphResourceHandle colorTarget_;
RenderGraphResourceHandle depthTarget_;
};
/**
* @brief 后期处理渲染通道
*/
class PostProcessRenderPass : public RenderPass {
public:
PostProcessRenderPass(const std::string& name);
const char* getName() const override { return name_.c_str(); }
void declareResources(RenderGraphBuilder& builder) override;
void execute(const RenderPassContext& ctx) override;
/**
* @brief 设置输入纹理
*/
void setInputTexture(RenderGraphResourceHandle handle) { inputTexture_ = handle; }
/**
* @brief 设置输出目标
*/
void setOutputTarget(RenderGraphResourceHandle handle) { outputTarget_ = handle; }
private:
std::string name_;
RenderGraphResourceHandle inputTexture_;
RenderGraphResourceHandle outputTarget_;
};
} // namespace extra2d