Restructure SpriteBatch internal vertex data

This commit is contained in:
Alex Szpakowski
2020-11-03 22:12:56 -04:00
parent c12b46da98
commit 7a18190c5c
2 changed files with 57 additions and 35 deletions
+51 -33
View File
@@ -47,6 +47,9 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage
, color(255, 255, 255, 255)
, colorf(1.0f, 1.0f, 1.0f, 1.0f)
, array_buf(nullptr)
, vertex_data(nullptr)
, modified_sprite_first(LOVE_INT32_MAX)
, modified_sprite_last(0)
, range_start(-1)
, range_count(-1)
{
@@ -64,14 +67,22 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage
vertex_stride = getFormatStride(vertex_format);
size_t vertex_size = vertex_stride * 4 * size;
vertex_data = (uint8 *) malloc(vertex_size);
if (vertex_data == nullptr)
throw love::Exception("Out of memory.");
memset(vertex_data, 0, vertex_size);
Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, usage);
auto decl = Buffer::getCommonFormatDeclaration(vertex_format);
array_buf = gfx->newBuffer(settings, decl, nullptr, vertex_size, 0);
array_buf.set(gfx->newBuffer(settings, decl, nullptr, vertex_size, 0), Acquire::NORETAIN);
}
SpriteBatch::~SpriteBatch()
{
delete array_buf;
free(vertex_data);
}
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
@@ -93,9 +104,10 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
const Vector2 *quadpositions = quad->getVertexPositions();
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// Always keep the buffer mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
int spriteindex = (index == -1 ? next : index);
size_t offset = spriteindex * vertex_stride * 4;
auto verts = (XYf_STf_RGBAub *) (vertex_data + offset);
m.transformXY(verts, quadpositions, 4);
@@ -106,7 +118,8 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
verts[i].color = color;
}
array_buf->setMappedRangeModified(offset, vertex_stride * 4);
modified_sprite_first = std::min(modified_sprite_first, spriteindex);
modified_sprite_last = std::max(modified_sprite_last, spriteindex);
// Increment counter.
if (index == -1)
@@ -137,9 +150,10 @@ int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
const Vector2 *quadpositions = quad->getVertexPositions();
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// Always keep the buffer mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
int spriteindex = (index == -1 ? next : index);
size_t offset = spriteindex * vertex_stride * 4;
auto verts = (XYf_STPf_RGBAub *) (vertex_data + offset);
m.transformXY(verts, quadpositions, 4);
@@ -151,7 +165,8 @@ int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
verts[i].color = color;
}
array_buf->setMappedRangeModified(offset, vertex_stride * 4);
modified_sprite_first = std::min(modified_sprite_first, spriteindex);
modified_sprite_last = std::max(modified_sprite_last, spriteindex);
// Increment counter.
if (index == -1)
@@ -168,7 +183,20 @@ void SpriteBatch::clear()
void SpriteBatch::flush()
{
array_buf->unmap();
if (modified_sprite_first <= modified_sprite_last)
{
size_t offset = modified_sprite_first * vertex_stride * 4;
size_t size = (modified_sprite_last - modified_sprite_first) * vertex_stride * 4;
// TODO: switch this to fill() once it gets cleaned up.
memcpy(((uint8 *)array_buf->map() + offset), vertex_data + offset, size);
array_buf->setMappedRangeModified(offset, size);
array_buf->unmap();
modified_sprite_first = LOVE_INT32_MAX;
modified_sprite_last = 0;
}
}
void SpriteBatch::setTexture(Texture *newtexture)
@@ -213,33 +241,24 @@ void SpriteBatch::setBufferSize(int newsize)
return;
size_t vertex_size = vertex_stride * 4 * newsize;
love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize);
try
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getMapFlags(), array_buf->getUsage());
auto decl = Buffer::getCommonFormatDeclaration(vertex_format);
new_array_buf = gfx->newBuffer(settings, decl, nullptr, vertex_size, 0);
void *new_vertex_data = realloc(vertex_data, vertex_size);
if (new_vertex_data == nullptr)
throw love::Exception("Out of memory.");
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = vertex_stride * 4 * new_next;
array_buf->copyTo(0, copy_size, new_array_buf, 0);
}
catch (love::Exception &)
{
delete new_array_buf;
throw;
}
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getMapFlags(), array_buf->getUsage());
auto decl = Buffer::getCommonFormatDeclaration(vertex_format);
// We don't need to unmap the old GLBuffer since we're deleting it.
delete array_buf;
array_buf.set(gfx->newBuffer(settings, decl, nullptr, vertex_size, 0), Acquire::NORETAIN);
array_buf->fill(0, vertex_stride * 4 * new_next, new_vertex_data);
vertex_data = (uint8 *) new_vertex_data;
array_buf = new_array_buf;
size = newsize;
next = new_next;
}
@@ -319,8 +338,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
Shader::current->checkMainTexture(texture);
}
// Make sure the buffer isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
flush(); // Upload any modified sprite data to the GPU.
VertexAttributes attributes;
BufferBindings buffers;
+6 -2
View File
@@ -130,8 +130,12 @@ private:
CommonFormat vertex_format;
size_t vertex_stride;
love::graphics::Buffer *array_buf;
StrongRef<love::graphics::Buffer> array_buf;
uint8 *vertex_data;
int modified_sprite_first;
int modified_sprite_last;
std::unordered_map<std::string, AttachedAttribute> attached_attributes;