feat: GPUDriven 实例化渲染——draw 数与实体数解耦

- UniformBuffer ring 支持 eStorageBuffer usage(GPUDriven 实例矩阵
  per-frame-slot,正确性保证与 UBO 一致:fence 等待后写入)
- DescriptorManager 加 UpdateStorageBuffer;池补 STORAGE_BUFFER 类型
- Set0 新增 binding1 = 实例矩阵 SSBO(vertex 读取,std430)
- Forward pass 重写:每帧从 ECS 收集实例矩阵(按 mesh 聚合 batch,
  两趟遍历保证 batch 区间连续),同 mesh 的 N 个实体合并为
  一次 drawIndexed(instanceCount=N),firstInstance 指向 batch 起点;
  vertex shader 经 gl_InstanceIndex 取模型矩阵,forward 不再用 push
- draw 数 = 唯一 mesh 数,与实体数量解耦(4096 实例上限,
  超出截断告警;聚合改哈希为后续 TODO)

验证:8 pass 全活,validation 0 error 0 warning,GPU Timings 面板
实测各 pass 毫秒,场景渲染与阴影正确
This commit is contained in:
2026-09-22 19:46:17 +08:00
parent 41e4cc85d5
commit 7fca721a24
10 changed files with 138 additions and 50 deletions
+2 -2
View File
@@ -55,10 +55,10 @@ namespace Engine
STATS.RemoveMesh(m_VertexBytes, m_IndexBytes);
}
void Mesh::Draw(vk::CommandBuffer cmd) const
void Mesh::Draw(vk::CommandBuffer cmd, u32 instanceCount, u32 firstInstance) const
{
cmd.bindVertexBuffers(0, m_VertexBuffer->Get(), {0});
cmd.bindIndexBuffer(m_IndexBuffer->Get(), 0, vk::IndexType::eUint32);
cmd.drawIndexed(m_IndexCount, 1, 0, 0, 0);
cmd.drawIndexed(m_IndexCount, instanceCount, 0, 0, firstInstance);
}
} // namespace Engine