Add love.graphics.copyBuffer.

This commit is contained in:
Alex Szpakowski
2021-01-17 14:02:00 -04:00
parent e1f40b433d
commit e2838131f2
12 changed files with 89 additions and 1 deletions
+4
View File
@@ -50,6 +50,7 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDe
bool vertexbuffer = settings.typeFlags & TYPEFLAG_VERTEX;
bool texelbuffer = settings.typeFlags & TYPEFLAG_TEXEL;
bool storagebuffer = settings.typeFlags & TYPEFLAG_SHADER_STORAGE;
bool copydest = settings.typeFlags & TYPEFLAG_COPY_DEST;
if (!indexbuffer && !vertexbuffer && !texelbuffer && !storagebuffer)
throw love::Exception("Buffer must be created with at least one buffer type (index, vertex, texel, or shaderstorage).");
@@ -60,6 +61,9 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDe
if (storagebuffer && !caps.features[Graphics::FEATURE_GLSL4])
throw love::Exception("Shader Storage buffers are not supported on this system (GLSL 4 support is necessary.)");
if (copydest && usage == BUFFERUSAGE_STREAM)
throw love::Exception("Buffers created with 'stream' usage cannot be a copy destination.");
size_t offset = 0;
size_t stride = 0;
size_t structurealignment = 1;
+7
View File
@@ -62,6 +62,8 @@ public:
TYPEFLAG_INDEX = 1 << BUFFERTYPE_INDEX,
TYPEFLAG_TEXEL = 1 << BUFFERTYPE_TEXEL,
TYPEFLAG_SHADER_STORAGE = 1 << BUFFERTYPE_SHADER_STORAGE,
TYPEFLAG_COPY_SOURCE = 1 << BUFFERTYPE_COPY_SOURCE,
TYPEFLAG_COPY_DEST = 1 << BUFFERTYPE_COPY_DEST,
};
struct DataDeclaration
@@ -136,6 +138,11 @@ public:
*/
virtual void fill(size_t offset, size_t size, const void *data) = 0;
/**
* Copy a portion of this Buffer's data to another buffer, using the GPU.
**/
virtual void copyTo(Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) = 0;
/**
* Texel buffers may use an additional texture handle as well as a buffer
* handle.
+27
View File
@@ -1039,6 +1039,32 @@ void Graphics::captureScreenshot(const ScreenshotInfo &info)
pendingScreenshotCallbacks.push_back(info);
}
void Graphics::copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
{
if (!capabilities.features[FEATURE_COPY_BUFFER])
throw love::Exception("Buffer copying is not supported on this system.");
if (!(source->getTypeFlags() & Buffer::TYPEFLAG_COPY_SOURCE))
throw love::Exception("Copy source buffer must be created with the copysource flag.");
if (!(dest->getTypeFlags() & Buffer::TYPEFLAG_COPY_DEST))
throw love::Exception("Copy destination buffer must be created with the copydest flag.");
Range sourcerange(sourceoffset, size);
Range destrange(destoffset, size);
if (sourcerange.getMax() >= source->getSize())
throw love::Exception("Buffer copy source offset and size doesn't fit within the source Buffer's size.");
if (destrange.getMax() >= dest->getSize())
throw love::Exception("Buffer copy destination offset and size doesn't fit within the destination buffer's size.");
if (source == dest && sourcerange.intersects(destrange))
throw love::Exception("Copying a portion of a buffer to the same buffer requires non-overlapping source and destination offsets.");
source->copyTo(dest, sourceoffset, destoffset, size);
}
Graphics::BatchedVertexData Graphics::requestBatchedDraw(const BatchedDrawCommand &cmd)
{
BatchedDrawState &state = batchedDrawState;
@@ -1835,6 +1861,7 @@ STRINGMAP_CLASS_BEGIN(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, f
{ "glsl4", Graphics::FEATURE_GLSL4 },
{ "instancing", Graphics::FEATURE_INSTANCING },
{ "texelbuffer", Graphics::FEATURE_TEXEL_BUFFER },
{ "copybuffer", Graphics::FEATURE_COPY_BUFFER },
}
STRINGMAP_CLASS_END(Graphics, Graphics::Feature, Graphics::FEATURE_MAX_ENUM, feature)
+3
View File
@@ -144,6 +144,7 @@ public:
FEATURE_GLSL4,
FEATURE_INSTANCING,
FEATURE_TEXEL_BUFFER,
FEATURE_COPY_BUFFER,
FEATURE_MAX_ENUM
};
@@ -668,6 +669,8 @@ public:
void captureScreenshot(const ScreenshotInfo &info);
void copyBuffer(Buffer *source, Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size);
void draw(Drawable *drawable, const Matrix4 &m);
void draw(Texture *texture, Quad *quad, const Matrix4 &m);
void drawLayer(Texture *texture, int layer, const Matrix4 &m);
+8
View File
@@ -253,6 +253,14 @@ void Buffer::fill(size_t offset, size_t size, const void *data)
}
}
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
{
gl.bindBuffer(BUFFERTYPE_COPY_SOURCE, buffer);
gl.bindBuffer(BUFFERTYPE_COPY_DEST, ((Buffer *) dest)->buffer);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sourceoffset, destoffset, size);
}
} // opengl
} // graphics
} // love
+1
View File
@@ -53,6 +53,7 @@ public:
void *map(MapType map, size_t offset, size_t size) override;
void unmap(size_t usedoffset, size_t usedsize) override;
void fill(size_t offset, size_t size, const void *data) override;
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
ptrdiff_t getHandle() const override { return buffer; };
ptrdiff_t getTexelBufferHandle() const override { return texture; };
+2 -1
View File
@@ -1531,7 +1531,8 @@ void Graphics::initCapabilities()
capabilities.features[FEATURE_GLSL4] = GLAD_ES_VERSION_3_1 || (gl.isCoreProfile() && GLAD_VERSION_4_3);
capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported();
capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_TEXEL);
static_assert(FEATURE_MAX_ENUM == 11, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_COPY_SOURCE);
static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize();
capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize();
+5
View File
@@ -621,6 +621,8 @@ GLenum OpenGL::getGLBufferType(BufferType type)
case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER;
case BUFFERTYPE_TEXEL: return GL_TEXTURE_BUFFER;
case BUFFERTYPE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER;
case BUFFERTYPE_COPY_SOURCE: return GL_COPY_READ_BUFFER;
case BUFFERTYPE_COPY_DEST: return GL_COPY_WRITE_BUFFER;
case BUFFERTYPE_MAX_ENUM: return GL_ZERO;
}
@@ -1444,6 +1446,9 @@ bool OpenGL::isBufferTypeSupported(BufferType type) const
return GLAD_VERSION_3_1;
case BUFFERTYPE_SHADER_STORAGE:
return (GLAD_VERSION_4_3 && isCoreProfile()) || GLAD_ES_VERSION_3_1;
case BUFFERTYPE_COPY_SOURCE:
case BUFFERTYPE_COPY_DEST:
return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0;
case BUFFERTYPE_MAX_ENUM:
return false;
}
+2
View File
@@ -343,6 +343,8 @@ STRINGMAP_BEGIN(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName)
{ "index", BUFFERTYPE_INDEX },
{ "texel", BUFFERTYPE_TEXEL },
{ "shaderstorage", BUFFERTYPE_SHADER_STORAGE },
{ "copysource", BUFFERTYPE_COPY_SOURCE },
{ "copydest", BUFFERTYPE_COPY_DEST },
}
STRINGMAP_END(BufferType, BUFFERTYPE_MAX_ENUM, bufferTypeName)
+2
View File
@@ -60,6 +60,8 @@ enum BufferType
BUFFERTYPE_INDEX,
BUFFERTYPE_TEXEL,
BUFFERTYPE_SHADER_STORAGE,
BUFFERTYPE_COPY_SOURCE,
BUFFERTYPE_COPY_DEST,
BUFFERTYPE_MAX_ENUM
};
+23
View File
@@ -3255,6 +3255,27 @@ int w_polygon(lua_State *L)
return 0;
}
int w_copyBuffer(lua_State *L)
{
Buffer *source = luax_checkbuffer(L, 1);
Buffer *dest = luax_checkbuffer(L, 2);
ssize_t sourceoffset = luaL_optinteger(L, 3, 0);
ssize_t destoffset = luaL_optinteger(L, 4, 0);
ssize_t size = std::min(source->getSize() - sourceoffset, dest->getSize() - destoffset);
if (!lua_isnoneornil(L, 5))
size = luaL_checkinteger(L, 5);
if (sourceoffset < 0 || destoffset < 0)
return luaL_error(L, "copyBuffer offsets cannot be negative.");
if (size <= 0)
return luaL_error(L, "copyBuffer size must be greater than 0.");
luax_catchexcept(L, [&](){ instance()->copyBuffer(source, dest, sourceoffset, destoffset, size); });
return 0;
}
int w_flushBatch(lua_State *)
{
instance()->flushBatchedDraws();
@@ -3451,6 +3472,8 @@ static const luaL_Reg functions[] =
{ "print", w_print },
{ "printf", w_printf },
{ "copyBuffer", w_copyBuffer },
{ "isCreated", w_isCreated },
{ "isActive", w_isActive },
{ "isGammaCorrect", w_isGammaCorrect },