Enhance OpenGLBuffer with more buffer types and features

- Add OpenGLBufferType enum (Vertex, Index, Uniform, CopyRead, CopyWrite, etc.)
- Add Initialize() method with buffer type parameter
- Add Map/Unmap for direct buffer access
- Add SetData for dynamic updates
- Add BindBase for buffer binding to indexed targets
- Add GetType and IsDynamic getters
This commit is contained in:
2026-03-17 02:08:49 +08:00
parent 4c9c03e1a7
commit 56c32bfbde
2 changed files with 90 additions and 20 deletions

View File

@@ -6,25 +6,47 @@
namespace XCEngine { namespace XCEngine {
namespace RHI { namespace RHI {
enum class OpenGLBufferType {
Vertex,
Index,
Uniform,
CopyRead,
CopyWrite,
AtomicCounter,
DispatchIndirect,
DrawIndirect,
ShaderBindingTable
};
class OpenGLBuffer { class OpenGLBuffer {
public: public:
OpenGLBuffer(); OpenGLBuffer();
~OpenGLBuffer(); ~OpenGLBuffer();
bool Initialize(OpenGLBufferType type, size_t size, const void* data = nullptr, bool dynamic = false);
bool InitializeVertexBuffer(const void* data, size_t size); bool InitializeVertexBuffer(const void* data, size_t size);
bool InitializeIndexBuffer(const void* data, size_t size); bool InitializeIndexBuffer(const void* data, size_t size);
void Shutdown(); void Shutdown();
void Bind() const; void Bind() const;
void Unbind() const; void Unbind() const;
void BindBase(unsigned int target, unsigned int index) const;
void* Map();
void Unmap();
void SetData(const void* data, size_t size, size_t offset = 0);
unsigned int GetID() const { return m_buffer; } unsigned int GetID() const { return m_buffer; }
size_t GetSize() const { return m_size; } size_t GetSize() const { return m_size; }
OpenGLBufferType GetType() const { return m_type; }
bool IsDynamic() const { return m_dynamic; }
private: private:
unsigned int m_buffer; unsigned int m_buffer;
size_t m_size; size_t m_size;
bool m_isIndexBuffer; bool m_isIndexBuffer;
bool m_dynamic;
OpenGLBufferType m_type;
}; };
} // namespace RHI } // namespace RHI

View File

@@ -6,32 +6,56 @@
namespace XCEngine { namespace XCEngine {
namespace RHI { namespace RHI {
static unsigned int ToGLBufferTarget(OpenGLBufferType type) {
switch (type) {
case OpenGLBufferType::Vertex: return GL_ARRAY_BUFFER;
case OpenGLBufferType::Index: return GL_ELEMENT_ARRAY_BUFFER;
case OpenGLBufferType::Uniform: return GL_UNIFORM_BUFFER;
case OpenGLBufferType::CopyRead: return GL_COPY_READ_BUFFER;
case OpenGLBufferType::CopyWrite: return GL_COPY_WRITE_BUFFER;
case OpenGLBufferType::AtomicCounter: return GL_ATOMIC_COUNTER_BUFFER;
case OpenGLBufferType::DispatchIndirect: return GL_DISPATCH_INDIRECT_BUFFER;
case OpenGLBufferType::DrawIndirect: return GL_DRAW_INDIRECT_BUFFER;
case OpenGLBufferType::ShaderBindingTable: return GL_SHADER_STORAGE_BUFFER;
default: return GL_ARRAY_BUFFER;
}
}
OpenGLBuffer::OpenGLBuffer() OpenGLBuffer::OpenGLBuffer()
: m_buffer(0) : m_buffer(0)
, m_size(0) , m_size(0)
, m_isIndexBuffer(false) { , m_isIndexBuffer(false)
, m_dynamic(false)
, m_type(OpenGLBufferType::Vertex) {
} }
OpenGLBuffer::~OpenGLBuffer() { OpenGLBuffer::~OpenGLBuffer() {
Shutdown(); Shutdown();
} }
bool OpenGLBuffer::InitializeVertexBuffer(const void* data, size_t size) { bool OpenGLBuffer::Initialize(OpenGLBufferType type, size_t size, const void* data, bool dynamic) {
glGenBuffers(1, &m_buffer); m_type = type;
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
m_size = size; m_size = size;
m_isIndexBuffer = false; m_dynamic = dynamic;
m_isIndexBuffer = (type == OpenGLBufferType::Index);
unsigned int target = ToGLBufferTarget(type);
GLenum usage = dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
glGenBuffers(1, &m_buffer);
glBindBuffer(target, m_buffer);
glBufferData(target, size, data, usage);
glBindBuffer(target, 0);
return true; return true;
} }
bool OpenGLBuffer::InitializeVertexBuffer(const void* data, size_t size) {
return Initialize(OpenGLBufferType::Vertex, size, data, false);
}
bool OpenGLBuffer::InitializeIndexBuffer(const void* data, size_t size) { bool OpenGLBuffer::InitializeIndexBuffer(const void* data, size_t size) {
glGenBuffers(1, &m_buffer); return Initialize(OpenGLBufferType::Index, size, data, false);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
m_size = size;
m_isIndexBuffer = true;
return true;
} }
void OpenGLBuffer::Shutdown() { void OpenGLBuffer::Shutdown() {
@@ -42,19 +66,43 @@ void OpenGLBuffer::Shutdown() {
} }
void OpenGLBuffer::Bind() const { void OpenGLBuffer::Bind() const {
if (m_isIndexBuffer) { unsigned int target = ToGLBufferTarget(m_type);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); glBindBuffer(target, m_buffer);
} else {
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
}
} }
void OpenGLBuffer::Unbind() const { void OpenGLBuffer::Unbind() const {
if (m_isIndexBuffer) { unsigned int target = ToGLBufferTarget(m_type);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(target, 0);
} else {
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void OpenGLBuffer::BindBase(unsigned int target, unsigned int index) const {
glBindBufferBase(target, index, m_buffer);
}
void* OpenGLBuffer::Map() {
unsigned int target = ToGLBufferTarget(m_type);
glBindBuffer(target, m_buffer);
void* ptr = glMapBuffer(target, GL_WRITE_ONLY);
glBindBuffer(target, 0);
return ptr;
}
void OpenGLBuffer::Unmap() {
unsigned int target = ToGLBufferTarget(m_type);
glBindBuffer(target, m_buffer);
glUnmapBuffer(target);
glBindBuffer(target, 0);
}
void OpenGLBuffer::SetData(const void* data, size_t size, size_t offset) {
unsigned int target = ToGLBufferTarget(m_type);
glBindBuffer(target, m_buffer);
if (offset == 0 && size == m_size) {
glBufferData(target, size, data, m_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
} else {
glBufferSubData(target, offset, size, data);
}
glBindBuffer(target, 0);
} }
} // namespace RHI } // namespace RHI