Extra2D/include/renderer/instance_buffer.h

209 lines
5.0 KiB
C++

#pragma once
#include <renderer/rhi/rhi.h>
#include <renderer/rhi/rhi_types.h>
#include <types/math/vec2.h>
#include <types/math/color.h>
#include <types/math/mat4.h>
#include <vector>
#include <memory>
namespace extra2d {
/**
* @brief 实例数据
*
* 单个实例的属性数据,用于实例化渲染
* 布局遵循 std140 对齐规则
*/
struct InstanceData {
// 第一组 16 字节
Vec2 position; // 位置偏移 (8 bytes)
float rotation; // 旋转角度 (4 bytes)
float padding0; // 填充到 16 字节对齐 (4 bytes)
// 第二组 16 字节
Vec2 scale; // 缩放 (8 bytes)
float padding1[2]; // 填充到 16 字节对齐 (8 bytes)
// 第三组 16 字节
Color color; // 颜色 (16 bytes) - r, g, b, a
// 第四组 16 字节
float uvX; // UV 起始 X (4 bytes)
float uvY; // UV 起始 Y (4 bytes)
float uvWidth; // UV 宽度 (4 bytes)
float uvHeight; // UV 高度 (4 bytes)
InstanceData()
: position(0.0f, 0.0f)
, rotation(0.0f)
, padding0(0.0f)
, scale(1.0f, 1.0f)
, padding1{0.0f, 0.0f}
, color(Color::White)
, uvX(0.0f)
, uvY(0.0f)
, uvWidth(1.0f)
, uvHeight(1.0f) {}
};
static_assert(sizeof(InstanceData) == 64, "InstanceData size should be 64 bytes for std140 alignment");
/**
* @brief 实例缓冲区
*
* 管理实例化渲染的实例数据缓冲区
* 支持动态更新和双缓冲
*/
class InstanceBuffer {
public:
/**
* @brief 默认构造函数
*/
InstanceBuffer();
/**
* @brief 析构函数
*/
~InstanceBuffer();
// 禁止拷贝
InstanceBuffer(const InstanceBuffer&) = delete;
InstanceBuffer& operator=(const InstanceBuffer&) = delete;
// 允许移动
InstanceBuffer(InstanceBuffer&& other) noexcept;
InstanceBuffer& operator=(InstanceBuffer&& other) noexcept;
/**
* @brief 初始化实例缓冲区
* @param maxInstances 最大实例数量
* @return 初始化是否成功
*/
bool initialize(uint32_t maxInstances);
/**
* @brief 关闭缓冲区
*/
void shutdown();
/**
* @brief 更新实例数据
* @param instances 实例数据数组
* @param count 实例数量
* @return 更新是否成功
*/
bool updateInstances(const InstanceData* instances, uint32_t count);
/**
* @brief 添加单个实例
* @param instance 实例数据
* @return 实例索引
*/
uint32_t addInstance(const InstanceData& instance);
/**
* @brief 清除所有实例
*/
void clear();
/**
* @brief 获取当前实例数量
* @return 实例数量
*/
uint32_t getInstanceCount() const { return instanceCount_; }
/**
* @brief 获取最大实例数量
* @return 最大实例数量
*/
uint32_t getMaxInstances() const { return maxInstances_; }
/**
* @brief 获取 RHI 缓冲区句柄
* @return 缓冲区句柄
*/
BufferHandle getBufferHandle() const { return bufferHandle_; }
/**
* @brief 获取 RHI 缓冲区指针
* @return 缓冲区指针
*/
RHIBuffer* getRHIBuffer() const { return bufferHandle_.get(); }
/**
* @brief 检查是否有效
* @return 是否有效
*/
bool isValid() const { return bufferHandle_.isValid(); }
private:
BufferHandle bufferHandle_; // RHI 缓冲区句柄
uint32_t maxInstances_ = 0; // 最大实例数量
uint32_t instanceCount_ = 0; // 当前实例数量
std::vector<InstanceData> cpuBuffer_; // CPU 端缓冲区
};
/**
* @brief 实例缓冲区管理器
*
* 管理多个实例缓冲区的分配和回收
*/
class InstanceBufferManager {
public:
/**
* @brief 默认构造函数
*/
InstanceBufferManager();
/**
* @brief 析构函数
*/
~InstanceBufferManager();
// 禁止拷贝
InstanceBufferManager(const InstanceBufferManager&) = delete;
InstanceBufferManager& operator=(const InstanceBufferManager&) = delete;
// 允许移动
InstanceBufferManager(InstanceBufferManager&& other) noexcept;
InstanceBufferManager& operator=(InstanceBufferManager&& other) noexcept;
/**
* @brief 初始化管理器
* @return 初始化是否成功
*/
bool initialize();
/**
* @brief 关闭管理器
*/
void shutdown();
/**
* @brief 获取或创建实例缓冲区
* @param minSize 最小容量(实例数量)
* @return 实例缓冲区指针
*/
InstanceBuffer* acquireBuffer(uint32_t minSize);
/**
* @brief 回收实例缓冲区
* @param buffer 缓冲区指针
*/
void releaseBuffer(InstanceBuffer* buffer);
/**
* @brief 重置所有缓冲区
*/
void reset();
private:
std::vector<std::unique_ptr<InstanceBuffer>> bufferPool_;
uint32_t currentBufferIndex_ = 0;
static constexpr uint32_t DEFAULT_BUFFER_SIZE = 1024;
};
} // namespace extra2d