refactor(渲染): 优化渲染排序和变换更新机制

- 将渲染命令排序键改为基于图层和深度,替代原有的材质纹理组合
- 引入变换版本号机制,避免冗余的世界变换计算
- 移除命令队列批次执行中的冗余全局UBO绑定
- 跳过仅含变换组件的节点渲染,提升渲染效率
This commit is contained in:
ChestnutYueyue 2026-03-16 18:38:45 +08:00
parent 690854698f
commit 2b552347fe
7 changed files with 71 additions and 36 deletions

View File

@ -411,9 +411,8 @@ private:
* @brief * @brief
* @param batchIndex * @param batchIndex
* @param batch * @param batch
* @param frameIndex
*/ */
void executeBatch(uint32_t batchIndex, const CommandBatch &batch, uint32_t frameIndex); void executeBatch(uint32_t batchIndex, const CommandBatch &batch);
/** /**
* @brief UBO 使 CPU * @brief UBO 使 CPU

View File

@ -102,6 +102,28 @@ struct RenderCommand {
Color getColor() const { return drawMesh.color; } Color getColor() const { return drawMesh.color; }
}; };
constexpr uint32_t SORT_KEY_LAYER_SHIFT = 24;
constexpr uint32_t SORT_KEY_DEPTH_SHIFT = 8;
constexpr uint32_t SORT_KEY_LAYER_MASK = 0xFF;
constexpr uint32_t SORT_KEY_DEPTH_MASK = 0xFFFF;
constexpr uint32_t SORT_KEY_FLAGS_MASK = 0xFF;
inline uint32_t makeSortKey(uint8_t layer, uint16_t depth, uint8_t flags = 0) {
return (static_cast<uint32_t>(layer) << SORT_KEY_LAYER_SHIFT) |
(static_cast<uint32_t>(depth) << SORT_KEY_DEPTH_SHIFT) |
static_cast<uint32_t>(flags);
}
inline uint8_t extractSortLayer(uint32_t sortKey) {
return static_cast<uint8_t>((sortKey >> SORT_KEY_LAYER_SHIFT) &
SORT_KEY_LAYER_MASK);
}
inline uint16_t extractSortDepth(uint32_t sortKey) {
return static_cast<uint16_t>((sortKey >> SORT_KEY_DEPTH_SHIFT) &
SORT_KEY_DEPTH_MASK);
}
// 清除标志 // 清除标志
constexpr uint32_t CLEAR_COLOR_FLAG = 1 << 0; constexpr uint32_t CLEAR_COLOR_FLAG = 1 << 0;
constexpr uint32_t CLEAR_DEPTH_FLAG = 1 << 1; constexpr uint32_t CLEAR_DEPTH_FLAG = 1 << 1;

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <scene/component.h> #include <scene/component.h>
#include <cstdint>
#include <types/math/transform.h> #include <types/math/transform.h>
#include <types/math/vec2.h> #include <types/math/vec2.h>
#include <types/math/mat4.h> #include <types/math/mat4.h>
@ -150,6 +151,7 @@ public:
* @return * @return
*/ */
bool isDirty() const { return dirty_; } bool isDirty() const { return dirty_; }
uint64_t getWorldVersion() const;
private: private:
/** /**
@ -160,6 +162,10 @@ private:
Transform local_; Transform local_;
mutable Transform world_; mutable Transform world_;
mutable bool dirty_ = true; mutable bool dirty_ = true;
uint64_t localVersion_ = 1;
mutable uint64_t cachedLocalVersion_ = 0;
mutable uint64_t cachedParentVersion_ = 0;
mutable uint64_t worldVersion_ = 0;
Vec2 anchor_ = Vec2(0.5f, 0.5f); Vec2 anchor_ = Vec2(0.5f, 0.5f);
Vec2 size_ = Vec2(100.0f, 100.0f); Vec2 size_ = Vec2(100.0f, 100.0f);
}; };

View File

@ -366,8 +366,8 @@ void CommandQueue::submitDraw(Ptr<Material> material, Ptr<Mesh> mesh,
// 构建排序键 // 构建排序键
uint32_t materialId = getMaterialId(material.get()); uint32_t materialId = getMaterialId(material.get());
uint16_t depth = static_cast<uint16_t>((sortKey >> 8) & 0xFFFF); uint16_t depth = extractSortDepth(sortKey);
uint8_t layer = static_cast<uint8_t>(sortKey & 0xFF); uint8_t layer = extractSortLayer(sortKey);
cmd.key = DrawKey::make(materialId, depth, layer); cmd.key = DrawKey::make(materialId, depth, layer);
// 设置管线 // 设置管线
@ -500,8 +500,16 @@ void CommandQueue::execute(uint32_t frameIndex) {
// 执行批次 // 执行批次
const auto executeStart = Clock::now(); const auto executeStart = Clock::now();
if (uboManager_) {
UniformBuffer *globalUBO = uboManager_->getGlobalUBO(frameIndex);
if (globalUBO) {
commandList_->setUniformBuffer(0, globalUBO->getRHIBuffer());
stats_.bufferBinds++;
}
}
for (uint32_t i = 0; i < batcher_.getBatchCount(); ++i) { for (uint32_t i = 0; i < batcher_.getBatchCount(); ++i) {
executeBatch(i, batcher_.getBatch(i), frameIndex); executeBatch(i, batcher_.getBatch(i));
} }
// 提交命令到 GPU // 提交命令到 GPU
@ -521,8 +529,7 @@ void CommandQueue::execute(uint32_t frameIndex) {
std::chrono::duration<float, std::milli>(executeEnd - totalStart).count(); std::chrono::duration<float, std::milli>(executeEnd - totalStart).count();
} }
void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch, void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch) {
uint32_t frameIndex) {
if (!commandList_) { if (!commandList_) {
return; return;
} }
@ -535,15 +542,6 @@ void CommandQueue::executeBatch(uint32_t batchIndex, const CommandBatch &batch,
E2D_WARN("批次没有有效的管线!"); E2D_WARN("批次没有有效的管线!");
} }
// 绑定全局 UBO (binding = 0) - 使用双缓冲
if (uboManager_) {
UniformBuffer *globalUBO = uboManager_->getGlobalUBO(frameIndex);
if (globalUBO) {
commandList_->setUniformBuffer(0, globalUBO->getRHIBuffer());
stats_.bufferBinds++;
}
}
// 绑定纹理 // 绑定纹理
if (batch.textureCount > 0) { if (batch.textureCount > 0) {
for (uint32_t i = 0; i < batch.textureCount; ++i) { for (uint32_t i = 0; i < batch.textureCount; ++i) {

View File

@ -29,9 +29,9 @@ void SpriteRenderer::render() {
RenderCommand cmd; RenderCommand cmd;
cmd.type = RenderCommandType::DrawMesh; cmd.type = RenderCommandType::DrawMesh;
uint32_t materialId = material_.index(); int32 layerTag = owner_->getTag();
uint32_t textureId = texture_.index(); uint8_t layer = layerTag < 0 ? 0 : static_cast<uint8_t>(layerTag & 0xFF);
cmd.sortKey = (materialId << 16) | (textureId & 0xFFFF); cmd.sortKey = makeSortKey(layer, 0);
// 如果没有指定网格,使用默认的四边形网格 // 如果没有指定网格,使用默认的四边形网格
cmd.drawMesh.mesh = Handle<Mesh>::invalid(); // RendererModule 会使用默认网格 cmd.drawMesh.mesh = Handle<Mesh>::invalid(); // RendererModule 会使用默认网格

View File

@ -70,14 +70,7 @@ Vec2 TransformComponent::getAnchorOffset() const {
void TransformComponent::setDirty() { void TransformComponent::setDirty() {
dirty_ = true; dirty_ = true;
// 递归标记所有子节点为脏 ++localVersion_;
if (owner_) {
for (auto& child : owner_->getChildren()) {
if (auto* transform = child->getTransform()) {
transform->setDirty();
}
}
}
} }
/** /**
@ -87,7 +80,18 @@ void TransformComponent::setDirty() {
* 1x1的四边形配合64x64的尺寸会正确显示为64x64像素大小 * 1x1的四边形配合64x64的尺寸会正确显示为64x64像素大小
*/ */
void TransformComponent::updateWorldTransform() const { void TransformComponent::updateWorldTransform() const {
if (!dirty_) return; uint64_t parentVersion = 0;
Transform parentWorld;
if (owner_ && owner_->getParent()) {
if (auto* parentTransform = owner_->getParent()->getTransform()) {
parentWorld = parentTransform->getWorldTransform();
parentVersion = parentTransform->getWorldVersion();
}
}
if (!dirty_ && cachedLocalVersion_ == localVersion_ &&
cachedParentVersion_ == parentVersion) {
return;
}
// 计算本地旋转(度数转弧度) // 计算本地旋转(度数转弧度)
float rotRad = local_.rot * glm::pi<float>() / 180.0f; float rotRad = local_.rot * glm::pi<float>() / 180.0f;
@ -100,8 +104,6 @@ void TransformComponent::updateWorldTransform() const {
// 计算世界变换 // 计算世界变换
if (owner_ && owner_->getParent()) { if (owner_ && owner_->getParent()) {
// 有父节点,需要组合变换 // 有父节点,需要组合变换
Transform parentWorld = owner_->getParent()->getWorldTransform();
// 本地旋转后的锚点偏移 // 本地旋转后的锚点偏移
float rotatedOffsetX = anchorOffset.x * c - anchorOffset.y * s; float rotatedOffsetX = anchorOffset.x * c - anchorOffset.y * s;
float rotatedOffsetY = anchorOffset.x * s + anchorOffset.y * c; float rotatedOffsetY = anchorOffset.x * s + anchorOffset.y * c;
@ -135,6 +137,9 @@ void TransformComponent::updateWorldTransform() const {
} }
dirty_ = false; dirty_ = false;
cachedLocalVersion_ = localVersion_;
cachedParentVersion_ = parentVersion;
++worldVersion_;
} }
Transform TransformComponent::getWorldTransform() const { Transform TransformComponent::getWorldTransform() const {
@ -142,6 +147,11 @@ Transform TransformComponent::getWorldTransform() const {
return world_; return world_;
} }
uint64_t TransformComponent::getWorldVersion() const {
updateWorldTransform();
return worldVersion_;
}
Mat4 TransformComponent::getWorldMatrix() const { Mat4 TransformComponent::getWorldMatrix() const {
updateWorldTransform(); updateWorldTransform();

View File

@ -175,14 +175,12 @@ void Node::onExit() {
} }
void Node::update(float dt) { void Node::update(float dt) {
// 更新所有组件
for (auto& comp : components_) { for (auto& comp : components_) {
if (comp->isEnabled()) { if (comp.get() != transform_ && comp->isEnabled()) {
comp->update(dt); comp->update(dt);
} }
} }
// 递归更新子节点
for (auto& child : children_) { for (auto& child : children_) {
child->update(dt); child->update(dt);
} }
@ -191,14 +189,16 @@ void Node::update(float dt) {
void Node::render() { void Node::render() {
if (!visible_) return; if (!visible_) return;
// 渲染所有组件 if (children_.empty() && components_.size() == 1) {
return;
}
for (auto& comp : components_) { for (auto& comp : components_) {
if (comp->isEnabled()) { if (comp.get() != transform_ && comp->isEnabled()) {
comp->render(); comp->render();
} }
} }
// 递归渲染子节点
for (auto& child : children_) { for (auto& child : children_) {
child->render(); child->render();
} }