mirror of
https://github.com/love2d/love.git
synced 2026-08-19 20:19:42 +02:00
Restructure SpriteBatch internal vertex data
This commit is contained in:
@@ -47,6 +47,9 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage
|
|||||||
, color(255, 255, 255, 255)
|
, color(255, 255, 255, 255)
|
||||||
, colorf(1.0f, 1.0f, 1.0f, 1.0f)
|
, colorf(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
, array_buf(nullptr)
|
, array_buf(nullptr)
|
||||||
|
, vertex_data(nullptr)
|
||||||
|
, modified_sprite_first(LOVE_INT32_MAX)
|
||||||
|
, modified_sprite_last(0)
|
||||||
, range_start(-1)
|
, range_start(-1)
|
||||||
, range_count(-1)
|
, range_count(-1)
|
||||||
{
|
{
|
||||||
@@ -64,14 +67,22 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, BufferUsage
|
|||||||
vertex_stride = getFormatStride(vertex_format);
|
vertex_stride = getFormatStride(vertex_format);
|
||||||
|
|
||||||
size_t vertex_size = vertex_stride * 4 * size;
|
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);
|
Buffer::Settings settings(Buffer::TYPEFLAG_VERTEX, Buffer::MAP_EXPLICIT_RANGE_MODIFY, usage);
|
||||||
auto decl = Buffer::getCommonFormatDeclaration(vertex_format);
|
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()
|
SpriteBatch::~SpriteBatch()
|
||||||
{
|
{
|
||||||
delete array_buf;
|
free(vertex_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
|
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 *quadpositions = quad->getVertexPositions();
|
||||||
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
|
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
|
||||||
|
|
||||||
// Always keep the buffer mapped when adding data (it'll be unmapped on draw.)
|
int spriteindex = (index == -1 ? next : index);
|
||||||
size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
|
|
||||||
auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
|
size_t offset = spriteindex * vertex_stride * 4;
|
||||||
|
auto verts = (XYf_STf_RGBAub *) (vertex_data + offset);
|
||||||
|
|
||||||
m.transformXY(verts, quadpositions, 4);
|
m.transformXY(verts, quadpositions, 4);
|
||||||
|
|
||||||
@@ -106,7 +118,8 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
|
|||||||
verts[i].color = color;
|
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.
|
// Increment counter.
|
||||||
if (index == -1)
|
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 *quadpositions = quad->getVertexPositions();
|
||||||
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
|
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
|
||||||
|
|
||||||
// Always keep the buffer mapped when adding data (it'll be unmapped on draw.)
|
int spriteindex = (index == -1 ? next : index);
|
||||||
size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
|
|
||||||
auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
|
size_t offset = spriteindex * vertex_stride * 4;
|
||||||
|
auto verts = (XYf_STPf_RGBAub *) (vertex_data + offset);
|
||||||
|
|
||||||
m.transformXY(verts, quadpositions, 4);
|
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;
|
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.
|
// Increment counter.
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
@@ -168,7 +183,20 @@ void SpriteBatch::clear()
|
|||||||
|
|
||||||
void SpriteBatch::flush()
|
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)
|
void SpriteBatch::setTexture(Texture *newtexture)
|
||||||
@@ -213,33 +241,24 @@ void SpriteBatch::setBufferSize(int newsize)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
size_t vertex_size = vertex_stride * 4 * newsize;
|
size_t vertex_size = vertex_stride * 4 * newsize;
|
||||||
love::graphics::Buffer *new_array_buf = nullptr;
|
|
||||||
|
|
||||||
int new_next = std::min(next, newsize);
|
int new_next = std::min(next, newsize);
|
||||||
|
|
||||||
try
|
void *new_vertex_data = realloc(vertex_data, vertex_size);
|
||||||
{
|
if (new_vertex_data == nullptr)
|
||||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
throw love::Exception("Out of memory.");
|
||||||
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);
|
|
||||||
|
|
||||||
// Copy as much of the old data into the new GLBuffer as can fit.
|
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||||
size_t copy_size = vertex_stride * 4 * new_next;
|
Buffer::Settings settings(array_buf->getTypeFlags(), array_buf->getMapFlags(), array_buf->getUsage());
|
||||||
array_buf->copyTo(0, copy_size, new_array_buf, 0);
|
auto decl = Buffer::getCommonFormatDeclaration(vertex_format);
|
||||||
}
|
|
||||||
catch (love::Exception &)
|
|
||||||
{
|
|
||||||
delete new_array_buf;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't need to unmap the old GLBuffer since we're deleting it.
|
array_buf.set(gfx->newBuffer(settings, decl, nullptr, vertex_size, 0), Acquire::NORETAIN);
|
||||||
delete array_buf;
|
|
||||||
|
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;
|
size = newsize;
|
||||||
|
|
||||||
next = new_next;
|
next = new_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,8 +338,7 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
|||||||
Shader::current->checkMainTexture(texture);
|
Shader::current->checkMainTexture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the buffer isn't mapped when we draw (sends data to GPU if needed.)
|
flush(); // Upload any modified sprite data to the GPU.
|
||||||
array_buf->unmap();
|
|
||||||
|
|
||||||
VertexAttributes attributes;
|
VertexAttributes attributes;
|
||||||
BufferBindings buffers;
|
BufferBindings buffers;
|
||||||
|
|||||||
@@ -130,8 +130,12 @@ private:
|
|||||||
|
|
||||||
CommonFormat vertex_format;
|
CommonFormat vertex_format;
|
||||||
size_t vertex_stride;
|
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;
|
std::unordered_map<std::string, AttachedAttribute> attached_attributes;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user