mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Add new texel buffer type.
GLSL 3+ shaders can read from texel buffers by declaring a uniform samplerBuffer variable and calling texelFetch with a 0-based index, in the shader code. All attributes in a texel buffer's format array must have the same data format (e.g. all 'floatvec4' formats). Shader:send accepts a texel Buffer for samplerBuffer uniforms. Added 'texelbuffer' to love.graphics.getSupported (requires GLSL 3+ and desktop OpenGL). Added 'texelbuffersize' to love.graphics.getSystemLimits. Returns the max number of values in a texel buffer (array length multiplied by the number of attributes declared in the buffer's format array).
This commit is contained in:
@@ -35,13 +35,45 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
static GLenum getGLFormat(DataFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case DATAFORMAT_FLOAT: return GL_R32F;
|
||||
case DATAFORMAT_FLOAT_VEC2: return GL_RG32F;
|
||||
case DATAFORMAT_FLOAT_VEC3: return GL_RGB32F;
|
||||
case DATAFORMAT_FLOAT_VEC4: return GL_RGBA32F;
|
||||
case DATAFORMAT_INT32: return GL_R32I;
|
||||
case DATAFORMAT_INT32_VEC2: return GL_RG32I;
|
||||
case DATAFORMAT_INT32_VEC3: return GL_RGB32I;
|
||||
case DATAFORMAT_INT32_VEC4: return GL_RGBA32I;
|
||||
case DATAFORMAT_UINT32: return GL_R32UI;
|
||||
case DATAFORMAT_UINT32_VEC2: return GL_RG32UI;
|
||||
case DATAFORMAT_UINT32_VEC3: return GL_RGB32UI;
|
||||
case DATAFORMAT_UINT32_VEC4: return GL_RGBA32UI;
|
||||
case DATAFORMAT_UNORM8_VEC4: return GL_RGBA8;
|
||||
case DATAFORMAT_INT8_VEC4: return GL_RGBA8I;
|
||||
case DATAFORMAT_UINT8_VEC4: return GL_RGBA8UI;
|
||||
case DATAFORMAT_UNORM16_VEC2: return GL_RG16;
|
||||
case DATAFORMAT_UNORM16_VEC4: return GL_RGBA16;
|
||||
case DATAFORMAT_INT16_VEC2: return GL_RG16I;
|
||||
case DATAFORMAT_INT16_VEC4: return GL_RGBA16I;
|
||||
case DATAFORMAT_UINT16: return GL_R16UI;
|
||||
case DATAFORMAT_UINT16_VEC2: return GL_RG16UI;
|
||||
case DATAFORMAT_UINT16_VEC4: return GL_RGBA16UI;
|
||||
default: return GL_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength)
|
||||
: love::graphics::Buffer(gfx, settings, format, size, arraylength)
|
||||
{
|
||||
size = getSize();
|
||||
arraylength = getArrayLength();
|
||||
|
||||
if (typeFlags & TYPEFLAG_VERTEX)
|
||||
if (typeFlags & TYPEFLAG_TEXEL)
|
||||
mapType = BUFFERTYPE_TEXEL;
|
||||
else if (typeFlags & TYPEFLAG_VERTEX)
|
||||
mapType = BUFFERTYPE_VERTEX;
|
||||
else if (typeFlags & TYPEFLAG_INDEX)
|
||||
mapType = BUFFERTYPE_INDEX;
|
||||
@@ -62,8 +94,9 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st
|
||||
|
||||
if (!load(data != nullptr))
|
||||
{
|
||||
unloadVolatile();
|
||||
delete[] memoryMap;
|
||||
throw love::Exception("Could not load vertex buffer (out of VRAM?)");
|
||||
throw love::Exception("Could not create buffer (out of VRAM?)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,31 +108,45 @@ Buffer::~Buffer()
|
||||
|
||||
bool Buffer::loadVolatile()
|
||||
{
|
||||
if (buffer != 0)
|
||||
return true;
|
||||
|
||||
return load(true);
|
||||
}
|
||||
|
||||
void Buffer::unloadVolatile()
|
||||
{
|
||||
mapped = false;
|
||||
if (vbo != 0)
|
||||
gl.deleteBuffer(vbo);
|
||||
vbo = 0;
|
||||
if (buffer != 0)
|
||||
gl.deleteBuffer(buffer);
|
||||
buffer = 0;
|
||||
if (texture != 0)
|
||||
gl.deleteTexture(texture);
|
||||
texture = 0;
|
||||
}
|
||||
|
||||
bool Buffer::load(bool restore)
|
||||
{
|
||||
glGenBuffers(1, &vbo);
|
||||
gl.bindBuffer(mapType, vbo);
|
||||
|
||||
while (glGetError() != GL_NO_ERROR)
|
||||
/* Clear the error buffer. */;
|
||||
|
||||
glGenBuffers(1, &buffer);
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
|
||||
// Copy the old buffer only if 'restore' was requested.
|
||||
const GLvoid *src = restore ? memoryMap : nullptr;
|
||||
|
||||
// Note that if 'src' is '0', no data will be copied.
|
||||
glBufferData(target, (GLsizeiptr) getSize(), src, OpenGL::getGLBufferUsage(getUsage()));
|
||||
|
||||
if (getTypeFlags() & TYPEFLAG_TEXEL)
|
||||
{
|
||||
glGenTextures(1, &texture);
|
||||
gl.bindBufferTextureToUnit(texture, 0, false, true);
|
||||
|
||||
glTexBuffer(target, getGLFormat(getDataMember(0).decl.format), buffer);
|
||||
}
|
||||
|
||||
return (glGetError() == GL_NO_ERROR);
|
||||
}
|
||||
|
||||
@@ -123,7 +170,7 @@ void Buffer::unmapStatic(size_t offset, size_t size)
|
||||
return;
|
||||
|
||||
// Upload the mapped data to the buffer.
|
||||
gl.bindBuffer(mapType, vbo);
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, memoryMap + offset);
|
||||
}
|
||||
|
||||
@@ -133,7 +180,7 @@ void Buffer::unmapStream()
|
||||
|
||||
// "orphan" current buffer to avoid implicit synchronisation on the GPU:
|
||||
// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
|
||||
gl.bindBuffer(mapType, vbo);
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
glBufferData(target, (GLsizeiptr) getSize(), nullptr, glusage);
|
||||
|
||||
#if LOVE_WINDOWS
|
||||
@@ -224,16 +271,11 @@ void Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
setMappedRangeModified(offset, size);
|
||||
else
|
||||
{
|
||||
gl.bindBuffer(mapType, vbo);
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
glBufferSubData(target, (GLintptr) offset, (GLsizeiptr) size, data);
|
||||
}
|
||||
}
|
||||
|
||||
ptrdiff_t Buffer::getHandle() const
|
||||
{
|
||||
return vbo;
|
||||
}
|
||||
|
||||
void Buffer::copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset)
|
||||
{
|
||||
other->fill(otheroffset, size, memoryMap + offset);
|
||||
|
||||
Reference in New Issue
Block a user