Extra2D/src/renderer/renderer_module.cpp

277 lines
7.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <assets/assets_module.h>
#include <platform/window_module.h>
#include <renderer/render_graph.h>
#include <renderer/renderer_module.h>
#include <renderer/rhi_module.h>
#include <utils/logger.h>
namespace extra2d {
RendererModule::RendererModule() = default;
RendererModule::~RendererModule() = default;
bool RendererModule::init() {
E2D_LOG_INFO("Initializing RendererModule...");
// 绑定事件监听器
onRenderBeginListener_.bind([this]() { onRenderBegin(); });
onRenderSubmitListener_.bind(
[this](const RenderCommand &cmd) { onRenderSubmit(cmd); });
onRenderSetCameraListener_.bind(
[this](const Mat4 &viewProj) { onRenderSetCamera(viewProj); });
onRenderEndListener_.bind([this]() { onRenderEnd(); });
onResizeListener_.bind([this](int32 w, int32 h) { onResize(w, h); });
onShowListener_.bind([this]() { onWindowShow(); });
E2D_LOG_INFO("RendererModule initialized (waiting for window show)");
return true;
}
void RendererModule::onWindowShow() {
if (initialized_) {
return;
}
E2D_LOG_INFO("Initializing RendererModule context...");
// 初始化 RHI 模块
auto *rhiModule = RHIModule::get();
if (!rhiModule) {
E2D_LOG_ERROR("RHIModule not available");
return;
}
if (!rhiModule->getDevice()) {
// RHI 设备尚未初始化,这是正常的时序问题
// RHIModule 会在窗口显示后初始化设备,然后再次触发此函数
E2D_LOG_INFO("RHIDevice not ready yet, waiting for RHI initialization...");
return;
}
// 初始化渲染图
if (!renderGraph_.initialize()) {
E2D_LOG_ERROR("Failed to initialize RenderGraph");
return;
}
commandQueue_ = renderGraph_.getCommandQueue();
// 添加默认的几何渲染通道
auto geometryPass = std::make_unique<GeometryRenderPass>("Geometry");
renderGraph_.addPass(std::move(geometryPass));
E2D_LOG_INFO("Added default geometry render pass");
auto windowModule = getModule<WindowModule>();
if (!windowModule) {
E2D_LOG_ERROR("WindowModule not available");
return;
}
setViewport(0, 0, static_cast<int32>(windowModule->getSize().w),
static_cast<int32>(windowModule->getSize().h));
initialized_ = true;
E2D_LOG_INFO("RendererModule context initialized successfully");
}
void RendererModule::shutdown() {
E2D_LOG_INFO("Shutting down RendererModule...");
renderGraph_.shutdown();
commandQueue_ = nullptr;
initialized_ = false;
// 注意:事件监听器是值类型,会在析构时自动清理
E2D_LOG_INFO("RendererModule shutdown complete");
}
RHIContext *RendererModule::getRHIContext() const {
auto *rhiModule = RHIModule::get();
if (rhiModule && rhiModule->getDevice()) {
return rhiModule->getDevice()->getContext();
}
return nullptr;
}
Handle<Material> RendererModule::getDefaultMaterialHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultMaterial() : Handle<Material>::invalid();
}
Handle<Mesh> RendererModule::getDefaultQuadHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultQuad() : Handle<Mesh>::invalid();
}
Handle<Texture> RendererModule::getDefaultTextureHandle() const {
auto *assets = getAssets();
return assets ? assets->getDefaultTexture() : Handle<Texture>::invalid();
}
void RendererModule::setViewport(int32 x, int32 y, int32 width, int32 height) {
viewportX_ = x;
viewportY_ = y;
viewportWidth_ = width;
viewportHeight_ = height;
viewportAdapter_.update(width, height);
// 更新渲染图输出尺寸
renderGraph_.setOutputSize(static_cast<uint32_t>(width),
static_cast<uint32_t>(height));
// 通过 RHI 设置视口
if (initialized_) {
auto *context = getRHIContext();
if (context) {
auto result = viewportAdapter_.getResult();
context->setViewport(static_cast<int32_t>(result.viewport.x),
static_cast<int32_t>(result.viewport.y),
static_cast<uint32_t>(result.viewport.w),
static_cast<uint32_t>(result.viewport.h));
}
}
}
void RendererModule::clear(const Color &color, uint32 flags) {
if (!initialized_)
return;
if (commandQueue_) {
commandQueue_->submitClear(color, flags);
}
}
void RendererModule::onRenderBegin() {
if (!initialized_) {
return;
}
// 重置统计
stats_ = {};
// 开始渲染帧 - 清空命令队列准备接收新的渲染命令
if (commandQueue_) {
commandQueue_->beginFrame();
}
// 帧开始
}
void RendererModule::onRenderSubmit(const RenderCommand &cmd) {
if (!initialized_ || !commandQueue_) {
E2D_LOG_WARN(
"onRenderSubmit: RendererModule not initialized or no command queue");
return;
}
(void)cmd; // 避免未使用警告
// 将渲染命令转换为绘制命令提交到队列
switch (cmd.type) {
case RenderCommandType::DrawMesh: {
auto *assets = getAssets();
if (!assets)
return;
// 获取材质,如果没有指定则使用默认材质
Material *material = assets->get(cmd.drawMesh.material);
if (!material) {
material = assets->get(assets->getDefaultMaterial());
}
// 获取网格,如果没有指定则使用默认四边形
Mesh *mesh = assets->get(cmd.drawMesh.mesh);
if (!mesh) {
mesh = assets->get(assets->getDefaultQuad());
}
if (material && mesh) {
Transform transform(cmd.drawMesh.pos, cmd.drawMesh.scale,
cmd.drawMesh.rot);
commandQueue_->submitDraw(Ptr<Material>(material), Ptr<Mesh>(mesh),
transform, cmd.drawMesh.color);
stats_.commandsSubmitted++;
} else {
E2D_LOG_WARN("Failed to submit draw command: material={}, mesh={}",
material ? "valid" : "null", mesh ? "valid" : "null");
}
break;
}
case RenderCommandType::SetViewport: {
setViewport(cmd.viewport.x, cmd.viewport.y, cmd.viewport.width,
cmd.viewport.height);
break;
}
case RenderCommandType::Clear: {
clear(cmd.clear.color, cmd.clear.flags);
break;
}
}
}
void RendererModule::onRenderSetCamera(const Mat4 &viewProj) {
if (!initialized_) {
return;
}
viewProjectionMatrix_ = viewProj;
// 更新全局 UBO通过 RenderGraph 的命令队列)
// 实际的 UBO 更新会在 RenderGraph 执行时进行
}
void RendererModule::onRenderEnd() {
if (!initialized_) {
E2D_LOG_WARN("onRenderEnd: RendererModule not initialized");
return;
}
// 执行渲染图,传递视图投影矩阵
renderGraph_.execute(0.016f, viewProjectionMatrix_);
// 获取统计信息
if (commandQueue_) {
const auto& stats = commandQueue_->getStats();
stats_.drawCalls = stats.drawCalls;
// 每60帧输出一次统计信息
static uint32_t frameCount = 0;
if (++frameCount % 60 == 0) {
E2D_LOG_INFO("Render Stats: DrawCalls={}, Triangles={}, Vertices={}, PipelineBinds={}, TextureBinds={}, BufferBinds={}",
stats.drawCalls, stats.triangles, stats.vertices,
stats.pipelineBinds, stats.textureBinds, stats.bufferBinds);
}
}
// 渲染完成
}
void RendererModule::onResize(int32 width, int32 height) {
setViewport(0, 0, width, height);
}
void RendererModule::executeCommand(const RenderCommand &cmd) {
// 此方法保留用于直接执行特定命令
// 大部分命令现在通过 RenderGraph 处理
switch (cmd.type) {
case RenderCommandType::SetViewport:
setViewport(cmd.viewport.x, cmd.viewport.y, cmd.viewport.width,
cmd.viewport.height);
break;
case RenderCommandType::Clear:
clear(cmd.clear.color, cmd.clear.flags);
break;
default:
break;
}
}
} // namespace extra2d