158 lines
3.2 KiB
C
158 lines
3.2 KiB
C
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include <glad/glad.h>
|
|||
|
|
#include <memory>
|
|||
|
|
#include <renderer/render_types.h>
|
|||
|
|
#include <vector>
|
|||
|
|
|
|||
|
|
namespace extra2d {
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 统一缓冲区对象 (UBO)
|
|||
|
|
*
|
|||
|
|
* 用于高效地传递 uniform 数据到 GPU
|
|||
|
|
* 支持 std140 布局标准
|
|||
|
|
*/
|
|||
|
|
class UniformBuffer {
|
|||
|
|
public:
|
|||
|
|
/**
|
|||
|
|
* @brief 默认构造函数
|
|||
|
|
*/
|
|||
|
|
UniformBuffer();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 析构函数
|
|||
|
|
*/
|
|||
|
|
~UniformBuffer();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 创建 UBO
|
|||
|
|
* @param size 缓冲区大小(字节)
|
|||
|
|
* @param binding 绑定槽位
|
|||
|
|
* @return 创建是否成功
|
|||
|
|
*/
|
|||
|
|
bool create(uint32_t size, uint32_t binding);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 销毁 UBO
|
|||
|
|
*/
|
|||
|
|
void destroy();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 更新缓冲区数据
|
|||
|
|
* @param data 数据源指针
|
|||
|
|
* @param size 数据大小
|
|||
|
|
* @param offset 缓冲区偏移(字节)
|
|||
|
|
*/
|
|||
|
|
void update(const void *data, uint32_t size, uint32_t offset = 0);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 绑定到指定槽位
|
|||
|
|
* @param binding 绑定槽位
|
|||
|
|
*/
|
|||
|
|
void bind(uint32_t binding);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取缓冲区大小
|
|||
|
|
* @return 缓冲区大小
|
|||
|
|
*/
|
|||
|
|
uint32_t getSize() const { return size_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取 OpenGL 缓冲区对象
|
|||
|
|
* @return OpenGL 缓冲区对象
|
|||
|
|
*/
|
|||
|
|
GLuint getHandle() const { return ubo_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查是否有效
|
|||
|
|
* @return 是否有效
|
|||
|
|
*/
|
|||
|
|
bool isValid() const { return ubo_ != 0; }
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
GLuint ubo_ = 0; // OpenGL 缓冲区对象
|
|||
|
|
uint32_t size_ = 0; // 缓冲区大小
|
|||
|
|
uint32_t binding_ = 0; // 绑定槽位
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief UBO 管理器
|
|||
|
|
*
|
|||
|
|
* 管理多个 UBO 的分配和回收
|
|||
|
|
* 支持每帧重置和对象池复用
|
|||
|
|
*/
|
|||
|
|
class UniformBufferManager {
|
|||
|
|
public:
|
|||
|
|
/**
|
|||
|
|
* @brief 默认构造函数
|
|||
|
|
*/
|
|||
|
|
UniformBufferManager();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 析构函数
|
|||
|
|
*/
|
|||
|
|
~UniformBufferManager();
|
|||
|
|
|
|||
|
|
// 禁止拷贝
|
|||
|
|
UniformBufferManager(const UniformBufferManager &) = delete;
|
|||
|
|
UniformBufferManager &operator=(const UniformBufferManager &) = delete;
|
|||
|
|
|
|||
|
|
// 允许移动
|
|||
|
|
UniformBufferManager(UniformBufferManager &&) noexcept;
|
|||
|
|
UniformBufferManager &operator=(UniformBufferManager &&) noexcept;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 初始化管理器
|
|||
|
|
* @return 初始化是否成功
|
|||
|
|
*/
|
|||
|
|
bool initialize();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 关闭管理器
|
|||
|
|
*/
|
|||
|
|
void shutdown();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取全局 UBO
|
|||
|
|
* @return 全局 UBO 指针
|
|||
|
|
*/
|
|||
|
|
UniformBuffer *getGlobalUBO();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取或创建材质 UBO
|
|||
|
|
* @param size 缓冲区大小
|
|||
|
|
* @return UBO 指针
|
|||
|
|
*/
|
|||
|
|
UniformBuffer *acquireMaterialUBO(uint32_t size);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 重置材质 UBO 池
|
|||
|
|
*
|
|||
|
|
* 每帧调用,重置当前索引以便复用 UBO
|
|||
|
|
*/
|
|||
|
|
void resetMaterialUBOs();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 更新全局 UBO 数据
|
|||
|
|
* @param data 数据指针
|
|||
|
|
* @param size 数据大小
|
|||
|
|
*/
|
|||
|
|
void updateGlobalUBO(const void *data, uint32_t size);
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
// 全局 UBO(用于 viewProjection、time 等全局数据)
|
|||
|
|
std::unique_ptr<UniformBuffer> globalUBO_;
|
|||
|
|
|
|||
|
|
// 材质 UBO 池
|
|||
|
|
std::vector<std::unique_ptr<UniformBuffer>> materialUBOPool_;
|
|||
|
|
uint32_t currentUBOIndex_ = 0;
|
|||
|
|
|
|||
|
|
// 常量
|
|||
|
|
static constexpr uint32_t INITIAL_UBO_POOL_SIZE = 16;
|
|||
|
|
static constexpr uint32_t GLOBAL_UBO_SIZE =
|
|||
|
|
256; // 足够存储 viewProjection + time + screenSize
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace extra2d
|