Program Listing for File buffer.cpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/rendering/data/buffer.cpp
)
#include <rendering/data/buffer.hpp>
namespace legion::rendering
{
buffer::buffer(GLenum target, size_type size, void* data, GLenum usage)
: m_id([](app::gl_id& value) { // Assign logic for buffer deletion to managed resource.
if (!app::ContextHelper::initialized())
return;
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to delete buffer with.");
return;
}
#endif
if (value)
glDeleteBuffers(1, &value);
}, invalid_id),
m_target(target),
m_usage(usage)
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to create buffer with.");
return;
}
#endif
glGenBuffers(1, &m_id); // Generate buffer
glBindBuffer(target, m_id); // First bind tells OpenGL what kind of buffer it will be.
glBufferData(target, size, data, usage); // Allocate VRAM
glBindBuffer(target, 0);
}
buffer::buffer(GLenum target, GLenum usage)
: m_id([](app::gl_id& value) { // Assign logic for buffer deletion to managed resource.
if (!app::ContextHelper::initialized())
return;
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to delete buffer with.");
return;
}
#endif
if (value)
glDeleteBuffers(1, &value);
}, invalid_id),
m_target(target),
m_usage(usage)
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to create buffer with.");
return;
}
#endif
glGenBuffers(1, &m_id); // Generate buffer
glBindBuffer(target, m_id); // First bind tells OpenGL what kind of buffer it will be.
glBindBuffer(target, 0);
}
L_NODISCARD app::gl_id buffer::id() const
{
return m_id;
}
L_NODISCARD GLenum buffer::target() const
{
return m_target;
}
L_NODISCARD GLenum buffer::usage() const
{
return m_usage;
}
L_NODISCARD size_type buffer::size() const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to read data from.");
return 0;
}
#endif
size_type size;
glBindBuffer(m_target, m_id);
glGetBufferParameteri64v(m_target, GL_BUFFER_SIZE, reinterpret_cast<GLint64*>(&size)); // Fetch VRAM size of the currently bound buffer.
glBindBuffer(m_target, 0);
return size;
}
void buffer::bindBufferBase(uint index) const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
if (m_target != GL_ATOMIC_COUNTER_BUFFER && m_target != GL_TRANSFORM_FEEDBACK_BUFFER && m_target != GL_UNIFORM_BUFFER && m_target != GL_SHADER_STORAGE_BUFFER)
{
log::error("Attempt at binding buffer base of an invalid target. Target must be GL_ATOMIC_COUNTER_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER, GL_UNIFORM_BUFFER or GL_SHADER_STORAGE_BUFFER. id: {}", m_id.value);
return;
}
#endif
glBindBuffer(m_target, m_id);
glBindBufferBase(m_target, index, m_id); // Bind to indexed buffer location.
glBindBuffer(m_target, 0);
}
void buffer::resize(size_type newSize) const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
#endif
glBindBuffer(m_target, m_id);
glBufferData(m_target, newSize, nullptr, m_usage); // Reallocate VRAM.
glBindBuffer(m_target, 0);
}
void buffer::bufferData(size_type size, void* data) const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
#endif
glBindBuffer(m_target, m_id);
size_type oldSize;
glGetBufferParameteri64v(m_target, GL_BUFFER_SIZE, reinterpret_cast<GLint64*>(&oldSize)); // Fetch the previous size of the buffer.
if (oldSize >= size)
glBufferSubData(m_target, 0, size, data); // If the new data fits within the already allocated VRAM then we don't want to reallocate.
else
glBufferData(m_target, size, data, m_usage); // If the new data does not fit within the already allocated VRAM we want to reallocate the buffer.
glBindBuffer(m_target, 0);
}
void buffer::bufferData(size_type offset, size_type size, void* data) const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
size_type oldSize;
glBindBuffer(m_target, m_id);
glGetBufferParameteri64v(m_target, GL_BUFFER_SIZE, reinterpret_cast<GLint64*>(&oldSize)); // Fetch VRAM size of the currently bound buffer.
glBindBuffer(m_target, 0);
if (offset + size > oldSize)
{
log::error("Offset + size cannot be more that the size of the buffer.");
return;
}
#endif
glBindBuffer(m_target, m_id);
glBufferSubData(m_target, offset, size, data); // Write data to already allocated VRAM.
glBindBuffer(m_target, 0);
}
void buffer::bind() const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
#endif
glBindBuffer(m_target, m_id);
}
void buffer::release() const
{
#if defined(LEGION_DEBUG)
if (!app::ContextHelper::getCurrentContext())
{
log::error("No current context to work with.");
return;
}
#endif
glBindBuffer(m_target, 0);
}
}