Files
HelloVulkan/Engine/include/Engine/Vulkan/UniformBuffer.h
T
atdunbg 7fca721a24 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 毫秒,场景渲染与阴影正确
2026-09-22 19:46:17 +08:00

52 lines
1.8 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.
//
// Created by atdunbg on 2026/9/20.
//
#ifndef HELLOVULKAN_UNIFORMBUFFER_H
#define HELLOVULKAN_UNIFORMBUFFER_H
#include <Engine/Core/Types.h>
#include <Engine/Core/FrameContext.h>
#include <Engine/Vulkan/Buffer.h>
#include <vulkan/vulkan.hpp>
#include <vector>
namespace Engine {
class Device;
class MemoryAllocator;
// Per-frame UBO ring:每个帧槽位一个独立 buffer。
//
// 正确性:CPU 在第 N 帧写 UBO 时,GPU 可能仍在读取第 N-1 帧的同槽位数据。
// 共享单个 buffer 会产生数据竞争;ring 化后每槽位的写入严格发生在
// 该槽位 fence 确认完成之后。
// 后续演进方向:单个大 ring buffer + 动态 offset(省描述符、省内存),
// 接口已按"写入哪个槽位"设计,届时只是内部实现替换。
class UniformBuffer {
public:
// usage:默认 eUniformBuffer;GPUDriven 实例数据传 eStorageBuffer
//(ring 化的正确性保证对所有 per-frame 数据一致)
UniformBuffer(Device& device, MemoryAllocator& allocator,
u64 size, u32 frameCount,
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer);
~UniformBuffer() = default;
UniformBuffer(const UniformBuffer&) = delete;
UniformBuffer& operator=(const UniformBuffer&) = delete;
vk::Buffer Get(u32 frameSlot) const { return m_Buffers[frameSlot]->Get(); }
u64 GetSize() const { return m_Size; }
// 写入指定帧槽位的 UBO(仅在该槽位 fence 确认完成后调用)
void Update(u32 frameSlot, const void* data, u64 size);
private:
std::vector<Scope<Buffer>> m_Buffers;
u64 m_Size = 0;
};
} // namespace Engine
#endif //HELLOVULKAN_UNIFORMBUFFER_H