Add Buffer methods

flush, setArrayData, setElement, getElement, getElementCount, getElementStride, getSize, getFormat
This commit is contained in:
Alex Szpakowski
2020-07-25 19:48:54 -03:00
parent 1d087cc5c2
commit d75f5df80d
6 changed files with 264 additions and 6 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataDe
if (vertexbuffer)
{
if (decl.arraySize > 0)
if (decl.arrayLength > 0)
throw love::Exception("Arrays are not supported in vertex buffers.");
if (info.isMatrix)
+3 -3
View File
@@ -66,12 +66,12 @@ public:
{
std::string name;
DataFormat format;
int arraySize;
int arrayLength;
DataDeclaration(const std::string &name, DataFormat format, int arraySize = 0)
DataDeclaration(const std::string &name, DataFormat format, int arrayLength = 0)
: name(name)
, format(format)
, arraySize(arraySize)
, arrayLength(arrayLength)
{}
};
+1 -1
View File
@@ -200,7 +200,7 @@ void Buffer::setMappedRangeModified(size_t offset, size_t modifiedsize)
if (!isMappedDataModified)
{
modifiedOffset = offset;
modifiedSize = size;
modifiedSize = modifiedsize;
isMappedDataModified = true;
return;
}
+255
View File
@@ -20,6 +20,7 @@
#include "wrap_Buffer.h"
#include "Buffer.h"
#include "common/Data.h"
namespace love
{
@@ -185,8 +186,262 @@ Buffer *luax_checkbuffer(lua_State *L, int idx)
return luax_checktype<Buffer>(L, idx);
}
static int w_Buffer_flush(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
t->unmap();
return 0;
}
static int w_Buffer_setArrayData(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
int startindex = (int) luaL_optnumber(L, 3, 1) - 1;
int count = -1;
if (!lua_isnoneornil(L, 4))
{
count = (int) luaL_checknumber(L, 4);
if (count <= 0)
return luaL_error(L, "Element count must be greater than 0.");
}
size_t stride = t->getArrayStride();
size_t offset = startindex * stride;
int arraylength = (int) t->getArrayLength();
if (startindex >= arraylength || startindex < 0)
return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", arraylength);
if (luax_istype(L, 2, Data::type))
{
Data *d = luax_checktype<Data>(L, 2);
count = count >= 0 ? count : (arraylength - startindex);
if (startindex + count > arraylength)
return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count);
size_t datasize = std::min(d->getSize(), count * stride);
char *bytedata = (char *) t->map() + offset;
memcpy(bytedata, d->getData(), datasize);
t->setMappedRangeModified(offset, datasize);
t->unmap();
return 0;
}
const std::vector<Buffer::DataMember> &members = t->getDataMembers();
int ncomponents = 0;
for (const Buffer::DataMember &member : members)
ncomponents += member.info.components;
luaL_checktype(L, 2, LUA_TTABLE);
int tablelen = (int) luax_objlen(L, 2);
lua_rawgeti(L, 2, 1);
bool tableoftables = lua_istable(L, -1);
lua_pop(L, 1);
if (!tableoftables)
{
if (tablelen % ncomponents != 0)
return luaL_error(L, "Array length in flat array variant of Buffer:setArrayData must be a multiple of the number of the total number of components (%d)", ncomponents);
tablelen /= ncomponents;
}
count = count >= 0 ? std::min(count, tablelen) : tablelen;
if (startindex + count > arraylength)
return luaL_error(L, "Too many array elements (expected at most %d, got %d)", arraylength - startindex, count);
char *data = (char *) t->map() + offset;
if (tableoftables)
{
for (int i = 0; i < count; i++)
{
// get arraydata[index]
lua_rawgeti(L, 2, i + 1);
luaL_checktype(L, -1, LUA_TTABLE);
// get arraydata[index][j]
for (int j = 1; j <= ncomponents; j++)
lua_rawgeti(L, -j, j);
int idx = -ncomponents;
for (const Buffer::DataMember &member : members)
{
luax_writebufferdata(L, idx, member.decl.format, data + member.offset);
idx += member.info.components;
}
lua_pop(L, ncomponents + 1);
data += stride;
}
}
else // Flat array
{
for (int i = 0; i < count; i++)
{
// get arraydata[arrayindex * ncomponents + componentindex]
for (int componentindex = 1; componentindex <= ncomponents; componentindex++)
lua_rawgeti(L, 2, i * ncomponents + componentindex);
int idx = -ncomponents;
for (const Buffer::DataMember &member : members)
{
luax_writebufferdata(L, idx, member.decl.format, data + member.offset);
idx += member.info.components;
}
lua_pop(L, ncomponents);
data += stride;
}
}
t->setMappedRangeModified(offset, count * stride);
t->unmap();
return 0;
}
static int w_Buffer_setElement(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
size_t index = (size_t) (luaL_checkinteger(L, 2) - 1);
if (index >= t->getArrayLength())
return luaL_error(L, "Invalid Buffer element index: %ld", index);
size_t offset = index * t->getArrayStride();
char *data = (char *) t->map() + offset;
const auto &members = t->getDataMembers();
bool istable = lua_istable(L, 3);
int idx = istable ? 1 : 3;
if (istable)
{
for (const Buffer::DataMember &member : members)
{
int components = member.info.components;
for (int i = idx; i < idx + components; i++)
lua_rawgeti(L, 3, i);
luax_writebufferdata(L, -components, member.decl.format, data + member.offset);
idx += components;
lua_pop(L, components);
}
}
else
{
for (const Buffer::DataMember &member : members)
{
luax_writebufferdata(L, idx, member.decl.format, data + member.offset);
idx += member.info.components;
}
}
return 0;
}
static int w_Buffer_getElement(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
if ((t->getMapFlags() & Buffer::MAP_READ) == 0)
return luaL_error(L, "Buffer:getElement requires the buffer to be created with the 'cpureadable' setting set to true.");
size_t index = (size_t) (luaL_checkinteger(L, 2) - 1);
if (index >= t->getArrayLength())
return luaL_error(L, "Invalid Buffer element index: %ld", index);
size_t offset = index * t->getArrayStride();
const char *data = (const char *) t->map() + offset;
const auto &members = t->getDataMembers();
int n = 0;
for (const Buffer::DataMember &member : members)
{
luax_readbufferdata(L, member.decl.format, data + member.offset);
n += member.info.components;
}
return n;
}
static int w_Buffer_getElementCount(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
lua_pushinteger(L, t->getArrayLength());
return 1;
}
static int w_Buffer_getElementStride(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
lua_pushinteger(L, t->getArrayStride());
return 1;
}
static int w_Buffer_getSize(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
lua_pushinteger(L, t->getSize());
return 1;
}
static int w_Buffer_getFormat(lua_State *L)
{
Buffer *t = luax_checkbuffer(L, 1);
const auto &members = t->getDataMembers();
lua_createtable(L, (int) members.size(), 0);
for (size_t i = 0; i < members.size(); i++)
{
const Buffer::DataMember &member = members[i];
lua_createtable(L, 0, 4);
lua_pushstring(L, member.decl.name.c_str());
lua_setfield(L, -2, "name");
const char *formatstr = "unknown";
getConstant(member.decl.format, formatstr);
lua_pushstring(L, formatstr);
lua_setfield(L, -2, "format");
lua_pushinteger(L, member.decl.arrayLength);
lua_setfield(L, -2, "arraylength");
lua_pushinteger(L, member.offset);
lua_setfield(L, -2, "offset");
lua_rawseti(L, -2, i + 1);
}
return 1;
}
static const luaL_Reg w_Buffer_functions[] =
{
{ "flush", w_Buffer_flush },
{ "setArrayData", w_Buffer_setArrayData },
{ "setElement", w_Buffer_setElement },
{ "getElement", w_Buffer_getElement },
{ "getElementCount", w_Buffer_getElementCount },
{ "getElementStride", w_Buffer_getElementStride },
{ "getSize", w_Buffer_getSize },
{ "getFormat", w_Buffer_getFormat },
{ 0, 0 }
};
+1 -1
View File
@@ -55,7 +55,7 @@ int w_Mesh_setVertices(lua_State *L)
size_t byteoffset = vertstart * stride;
int totalverts = (int) t->getVertexCount();
if (vertstart >= totalverts)
if (vertstart >= totalverts || vertstart < 0)
return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", totalverts);
if (luax_istype(L, 2, Data::type))
@@ -226,6 +226,9 @@ int w_SpriteBatch_attachAttribute(lua_State *L)
{
Mesh *mesh = luax_checktype<Mesh>(L, 3);
buffer = mesh->getVertexBuffer();
if (buffer == nullptr)
return luaL_error(L, "Mesh does not have its own vertex buffer.");
luax_markdeprecated(L, "SpriteBatch:attachAttribute(name, mesh)", API_METHOD, DEPRECATED_REPLACED, "SpriteBatch:attachAttribute(name, buffer)");
}
luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer); });