Extra2D/include/renderer/uniform_buffer.h

198 lines
5.0 KiB
C
Raw Permalink Normal View History

#pragma once
#include <renderer/rhi/rhi.h>
#include <memory>
#include <vector>
namespace extra2d {
/**
* @brief (UBO)
*
* RHI 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 RHI
* @return RHI
*/
BufferHandle getHandle() const { return handle_; }
/**
* @brief RHI
* @return RHI
*/
RHIBuffer* getRHIBuffer() const;
/**
* @brief
* @return
*/
bool isValid() const { return handle_.isValid(); }
private:
BufferHandle handle_; // RHI 缓冲区句柄
uint32_t size_ = 0; // 缓冲区大小
uint32_t binding_ = 0; // 绑定槽位
};
/**
* @brief UBO
*
* UBO
*
* CPU-GPU
*/
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
* @param frameIndex
* @return UBO
*/
UniformBuffer* getGlobalUBO(uint32_t frameIndex);
/**
* @brief UBO
* @param size
* @return UBO
*/
UniformBuffer* acquireMaterialUBO(uint32_t size);
/**
* @brief UBO
*
* 便 UBO
*/
void resetMaterialUBOs();
/**
* @brief UBO
* @param data
* @param size
* @param frameIndex
*/
void updateGlobalUBO(const void* data, uint32_t size, uint32_t frameIndex);
/**
* @brief UBO
* @param data
* @param size
* @param offset
*/
void batchUpdateMaterialUBO(const void* data, uint32_t size, uint32_t offset);
/**
* @brief UBO CPU
* @return CPU
*/
uint8_t* getMaterialUBOBuffer() { return materialUBOBuffer_.data(); }
/**
* @brief UBO
* @return
*/
uint32_t getMaterialUBOBufferSize() const { return static_cast<uint32_t>(materialUBOBuffer_.size()); }
/**
* @brief UBO GPU
*/
void flushMaterialUBO();
private:
// 全局 UBO 双缓冲(用于 viewProjection、time 等全局数据)
std::array<std::unique_ptr<UniformBuffer>, 2> globalUBOs_;
// 材质 UBO 池
std::vector<std::unique_ptr<UniformBuffer>> materialUBOPool_;
uint32_t currentUBOIndex_ = 0;
// 材质 UBO CPU 缓冲区(用于批量更新)
std::vector<uint8_t> materialUBOBuffer_;
uint32_t materialUBOBufferOffset_ = 0;
UniformBuffer* currentMaterialUBO_ = nullptr;
// 常量
static constexpr uint32_t INITIAL_UBO_POOL_SIZE = 16;
static constexpr uint32_t GLOBAL_UBO_SIZE = 256; // 足够存储 viewProjection + time + screenSize
static constexpr uint32_t GLOBAL_UBO_BINDING = 0; // 全局 UBO 绑定槽位
static constexpr uint32_t MATERIAL_UBO_BINDING = 1; // 材质 UBO 绑定槽位
static constexpr uint32_t MATERIAL_UBO_BUFFER_SIZE = 1024 * 1024; // 1MB 材质 UBO 缓冲区
};
} // namespace extra2d