mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Add Buffer:clear, to reset all or part of a Buffer's contents to 0.
This commit is contained in:
@@ -131,6 +131,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool fill(size_t offset, size_t size, const void *data) = 0;
|
virtual bool fill(size_t offset, size_t size, const void *data) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the given portion of this buffer's data to 0.
|
||||||
|
*/
|
||||||
|
virtual void clear(size_t offset, size_t size) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a portion of this Buffer's data to another buffer, using the GPU.
|
* Copy a portion of this Buffer's data to another buffer, using the GPU.
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
void *map(MapType map, size_t offset, size_t size) override;
|
void *map(MapType map, size_t offset, size_t size) override;
|
||||||
void unmap(size_t usedoffset, size_t usedsize) override;
|
void unmap(size_t usedoffset, size_t usedsize) override;
|
||||||
bool fill(size_t offset, size_t size, const void *data) override;
|
bool fill(size_t offset, size_t size, const void *data) override;
|
||||||
|
void clear(size_t offset, size_t size) override;
|
||||||
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
|
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
|
||||||
|
|
||||||
ptrdiff_t getHandle() const override { return (ptrdiff_t) buffer; }
|
ptrdiff_t getHandle() const override { return (ptrdiff_t) buffer; }
|
||||||
|
|||||||
@@ -104,7 +104,16 @@ Buffer::Buffer(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settin
|
|||||||
{
|
{
|
||||||
auto *mgfx = (Graphics *) gfx;
|
auto *mgfx = (Graphics *) gfx;
|
||||||
auto encoder = mgfx->useBlitEncoder();
|
auto encoder = mgfx->useBlitEncoder();
|
||||||
[encoder fillBuffer:buffer range:NSMakeRange(0, size) value:0];
|
|
||||||
|
size_t clearsize = size;
|
||||||
|
|
||||||
|
#ifdef LOVE_MACOS
|
||||||
|
// Metal limitation on macOS.
|
||||||
|
clearsize -= (clearsize % 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (clearsize > 0)
|
||||||
|
[encoder fillBuffer:buffer range:NSMakeRange(0, clearsize) value:0];
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@@ -197,6 +206,23 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
|
|||||||
return true;
|
return true;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
void Buffer::clear(size_t offset, size_t size)
|
||||||
|
{ @autoreleasepool {
|
||||||
|
if (isImmutable())
|
||||||
|
throw love::Exception("Cannot clear an immutable Buffer.");
|
||||||
|
else if (isMapped())
|
||||||
|
throw love::Exception("Cannot clear a mapped Buffer.");
|
||||||
|
else if (offset + size > getSize())
|
||||||
|
throw love::Exception("The given offset and size parameters to clear() are not within the Buffer's size.");
|
||||||
|
else if (offset % 4 != 0 || size % 4 != 0)
|
||||||
|
throw love::Exception("clear() must be used with offset and size parameters that are multiples of 4 bytes.");
|
||||||
|
|
||||||
|
auto gfx = Graphics::getInstance();
|
||||||
|
auto encoder = gfx->useBlitEncoder();
|
||||||
|
|
||||||
|
[encoder fillBuffer:buffer range:NSMakeRange(offset, size) value:0];
|
||||||
|
}}
|
||||||
|
|
||||||
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
auto gfx = Graphics::getInstance();
|
auto gfx = Graphics::getInstance();
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st
|
|||||||
ownsMemoryMap = true;
|
ownsMemoryMap = true;
|
||||||
|
|
||||||
std::vector<uint8> emptydata;
|
std::vector<uint8> emptydata;
|
||||||
if (settings.zeroInitialize && data == nullptr)
|
if (settings.zeroInitialize && data == nullptr && !GLAD_VERSION_4_3)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -107,6 +107,12 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st
|
|||||||
unloadVolatile();
|
unloadVolatile();
|
||||||
throw love::Exception("Could not create buffer with %d bytes (out of VRAM?)", size);
|
throw love::Exception("Could not create buffer with %d bytes (out of VRAM?)", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.zeroInitialize && data == nullptr && GLAD_VERSION_4_3)
|
||||||
|
{
|
||||||
|
gl.bindBuffer(mapUsage, buffer);
|
||||||
|
glClearBufferData(target, GL_R8UI, GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer()
|
Buffer::~Buffer()
|
||||||
@@ -290,6 +296,36 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Buffer::clear(size_t offset, size_t size)
|
||||||
|
{
|
||||||
|
if (isImmutable())
|
||||||
|
throw love::Exception("Cannot clear an immutable Buffer.");
|
||||||
|
else if (isMapped())
|
||||||
|
throw love::Exception("Cannot clear a mapped Buffer.");
|
||||||
|
else if (offset + size > getSize())
|
||||||
|
throw love::Exception("The given offset and size parameters to clear() are not within the Buffer's size.");
|
||||||
|
else if (offset % 4 != 0 || size % 4 != 0)
|
||||||
|
throw love::Exception("clear() must be used with offset and size parameters that are multiples of 4 bytes.");
|
||||||
|
|
||||||
|
if (GLAD_VERSION_4_3)
|
||||||
|
{
|
||||||
|
gl.bindBuffer(mapUsage, buffer);
|
||||||
|
glClearBufferSubData(target, GL_R8UI, offset, size, GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::vector<uint8> emptydata(getSize());
|
||||||
|
fill(0, getSize(), emptydata.data());
|
||||||
|
}
|
||||||
|
catch (std::exception &)
|
||||||
|
{
|
||||||
|
throw love::Exception("Out of memory.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
||||||
{
|
{
|
||||||
// TODO: tracked state for these bind types?
|
// TODO: tracked state for these bind types?
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public:
|
|||||||
void *map(MapType map, size_t offset, size_t size) override;
|
void *map(MapType map, size_t offset, size_t size) override;
|
||||||
void unmap(size_t usedoffset, size_t usedsize) override;
|
void unmap(size_t usedoffset, size_t usedsize) override;
|
||||||
bool fill(size_t offset, size_t size, const void *data) override;
|
bool fill(size_t offset, size_t size, const void *data) override;
|
||||||
|
void clear(size_t offset, size_t size) override;
|
||||||
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) 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 getHandle() const override { return buffer; };
|
||||||
|
|||||||
@@ -254,6 +254,20 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Buffer::clear(size_t offset, size_t size)
|
||||||
|
{
|
||||||
|
if (isImmutable())
|
||||||
|
throw love::Exception("Cannot clear an immutable Buffer.");
|
||||||
|
else if (isMapped())
|
||||||
|
throw love::Exception("Cannot clear a mapped Buffer.");
|
||||||
|
else if (offset + size > getSize())
|
||||||
|
throw love::Exception("The given offset and size parameters to clear() are not within the Buffer's size.");
|
||||||
|
else if (offset % 4 != 0 || size % 4 != 0)
|
||||||
|
throw love::Exception("clear() must be used with offset and size parameters that are multiples of 4 bytes.");
|
||||||
|
|
||||||
|
vkCmdFillBuffer(vgfx->getCommandBufferForDataTransfer(), buffer, offset, size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
||||||
{
|
{
|
||||||
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public:
|
|||||||
void *map(MapType map, size_t offset, size_t size) override;
|
void *map(MapType map, size_t offset, size_t size) override;
|
||||||
void unmap(size_t usedoffset, size_t usedsize) override;
|
void unmap(size_t usedoffset, size_t usedsize) override;
|
||||||
bool fill(size_t offset, size_t size, const void *data) override;
|
bool fill(size_t offset, size_t size, const void *data) override;
|
||||||
|
void clear(size_t offset, size_t size) override;
|
||||||
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
|
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
|
||||||
ptrdiff_t getHandle() const override;
|
ptrdiff_t getHandle() const override;
|
||||||
ptrdiff_t getTexelBufferHandle() const override;
|
ptrdiff_t getTexelBufferHandle() const override;
|
||||||
|
|||||||
@@ -318,6 +318,24 @@ static int w_Buffer_setArrayData(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int w_Buffer_clear(lua_State *L)
|
||||||
|
{
|
||||||
|
Buffer *t = luax_checkbuffer(L, 1);
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t size = t->getSize();
|
||||||
|
if (!lua_isnoneornil(L, 2))
|
||||||
|
{
|
||||||
|
lua_Number offsetp = luaL_checknumber(L, 2);
|
||||||
|
lua_Number sizep = luaL_checknumber(L, 3);
|
||||||
|
if (offsetp < 0 || sizep < 0)
|
||||||
|
return luaL_error(L, "Offset and size parameters cannot be negative.");
|
||||||
|
offset = (size_t) offsetp;
|
||||||
|
size = (size_t) sizep;
|
||||||
|
}
|
||||||
|
luax_catchexcept(L, [&]() { t->clear(offset, size); });
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int w_Buffer_getElementCount(lua_State *L)
|
static int w_Buffer_getElementCount(lua_State *L)
|
||||||
{
|
{
|
||||||
Buffer *t = luax_checkbuffer(L, 1);
|
Buffer *t = luax_checkbuffer(L, 1);
|
||||||
@@ -386,6 +404,7 @@ static int w_Buffer_isBufferType(lua_State *L)
|
|||||||
static const luaL_Reg w_Buffer_functions[] =
|
static const luaL_Reg w_Buffer_functions[] =
|
||||||
{
|
{
|
||||||
{ "setArrayData", w_Buffer_setArrayData },
|
{ "setArrayData", w_Buffer_setArrayData },
|
||||||
|
{ "clear", w_Buffer_clear },
|
||||||
{ "getElementCount", w_Buffer_getElementCount },
|
{ "getElementCount", w_Buffer_getElementCount },
|
||||||
{ "getElementStride", w_Buffer_getElementStride },
|
{ "getElementStride", w_Buffer_getElementStride },
|
||||||
{ "getSize", w_Buffer_getSize },
|
{ "getSize", w_Buffer_getSize },
|
||||||
|
|||||||
Reference in New Issue
Block a user