mirror of
https://github.com/love2d/love.git
synced 2026-08-16 16:20:42 +02:00
Add love.graphics.copyBuffer.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; };
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ enum BufferType
|
||||
BUFFERTYPE_INDEX,
|
||||
BUFFERTYPE_TEXEL,
|
||||
BUFFERTYPE_SHADER_STORAGE,
|
||||
BUFFERTYPE_COPY_SOURCE,
|
||||
BUFFERTYPE_COPY_DEST,
|
||||
BUFFERTYPE_MAX_ENUM
|
||||
};
|
||||
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user