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:
@@ -30,7 +30,9 @@ namespace Engine
|
||||
Mesh(const Mesh&) = delete;
|
||||
Mesh& operator=(const Mesh&) = delete;
|
||||
|
||||
void Draw(vk::CommandBuffer cmd) const;
|
||||
// instanceCount/firstInstance:GPUDriven 按 mesh 分 batch 后,
|
||||
// 同 mesh 的 N 个实体一次 draw 完成,模型矩阵经实例索引取
|
||||
void Draw(vk::CommandBuffer cmd, u32 instanceCount = 1, u32 firstInstance = 0) const;
|
||||
|
||||
Material* GetMaterial() const { return m_Material.get(); }
|
||||
u32 GetIndexCount() const { return m_IndexCount; }
|
||||
|
||||
@@ -31,6 +31,14 @@ namespace Engine {
|
||||
namespace ECS { class Scene; }
|
||||
namespace Assets { class AssetManager; }
|
||||
class ImGuiLayer;
|
||||
class Mesh;
|
||||
|
||||
// GPUDriven:按 mesh 聚合的绘制批
|
||||
struct InstanceBatch {
|
||||
Mesh* mesh;
|
||||
u32 first; // 在实例矩阵数组中的起始下标
|
||||
u32 count; // 实例数
|
||||
};
|
||||
|
||||
// Renderer 职责(收敛后):
|
||||
// 1. 装配底层模块(Device/Swapchain/Sync/Command/Descriptor/Shader)
|
||||
@@ -78,6 +86,7 @@ namespace Engine {
|
||||
Scope<SyncManager> m_SyncManager;
|
||||
Scope<CommandManager> m_CommandManager;
|
||||
Scope<UniformBuffer> m_UniformBuffer;
|
||||
Scope<UniformBuffer> m_ObjectBuffer; // GPUDriven 实例矩阵 ring(SSBO)
|
||||
Scope<RG::RenderGraph> m_RenderGraph;
|
||||
|
||||
// ---- 管线装配(shader object 方案,无 vk::Pipeline)----
|
||||
@@ -128,6 +137,11 @@ namespace Engine {
|
||||
Assets::AssetManager* m_BoundAssets = nullptr;
|
||||
glm::mat4 m_LightSpace{1.0f}; // 阴影光源 VP(每帧由 Render 算好)
|
||||
|
||||
// GPUDriven:当帧实例数据(Render 期收集,Forward pass 消费)
|
||||
std::vector<InstanceBatch> m_InstanceBatches;
|
||||
std::vector<glm::mat4> m_InstanceModels;
|
||||
static constexpr u32 kMaxInstances = 4096;
|
||||
|
||||
// 可选叠加层(不拥有;Application 持有)
|
||||
ImGuiLayer* m_ImGuiLayer = nullptr;
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace Engine {
|
||||
|
||||
void UpdateUniformBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size);
|
||||
void UpdateStorageBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size);
|
||||
|
||||
void UpdateTexture(vk::DescriptorSet set, u32 binding,
|
||||
vk::Sampler sampler, vk::ImageView view);
|
||||
|
||||
@@ -25,8 +25,11 @@ namespace Engine {
|
||||
// 接口已按"写入哪个槽位"设计,届时只是内部实现替换。
|
||||
class UniformBuffer {
|
||||
public:
|
||||
// usage:默认 eUniformBuffer;GPUDriven 实例数据传 eStorageBuffer
|
||||
//(ring 化的正确性保证对所有 per-frame 数据一致)
|
||||
UniformBuffer(Device& device, MemoryAllocator& allocator,
|
||||
u64 size, u32 frameCount);
|
||||
u64 size, u32 frameCount,
|
||||
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer);
|
||||
~UniformBuffer() = default;
|
||||
|
||||
UniformBuffer(const UniformBuffer&) = delete;
|
||||
|
||||
Reference in New Issue
Block a user