Skip to content

Commit

Permalink
Merge pull request #131 from defold/vertex-data-perf-fix
Browse files Browse the repository at this point in the history
Fix for generating vertex data more efficiently
  • Loading branch information
JCash authored Mar 27, 2023
2 parents 56efba6 + 20c7ef4 commit 0eb81dd
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 16 deletions.
53 changes: 39 additions & 14 deletions defold-spine/commonsrc/vertices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,48 @@ void GetSkeletonBounds(const spSkeleton* skeleton, SpineModelBounds& bounds)

}

uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_triangle_count)
{
uint32_t count = 0;
uint32_t max_triangle_count = 8;
for (int s = 0; s < skeleton->slotsCount; ++s)
{
spSlot* slot = skeleton->drawOrder[s];

spAttachment* attachment = slot->attachment;
if (!attachment)continue;
if (attachment->type == SP_ATTACHMENT_REGION)
{
count += 6;
}
else if (attachment->type == SP_ATTACHMENT_MESH)
{
spMeshAttachment* mesh = (spMeshAttachment*)attachment;
uint32_t num_tri_vertices = SUPER(mesh)->worldVerticesLength;

count += (uint32_t)mesh->trianglesCount; // It's a list of indices, where each 3-tuple define a triangle
if (num_tri_vertices > max_triangle_count)
max_triangle_count = num_tri_vertices;
}
}
if (out_max_triangle_count)
*out_max_triangle_count = max_triangle_count;
return count;
}


uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world)
{
dmArray<float> scratch; // scratch buffer
static dmArray<float> scratch; // scratch buffer

int vindex = vertex_buffer.Size();
int vindex_start = vindex;

uint32_t max_triangle_count = 0;
uint32_t estimated_vcount = CalcVertexBufferSize(skeleton, &max_triangle_count);
EnsureArrayFitsNumber(scratch, max_triangle_count);
EnsureArrayFitsNumber(vertex_buffer, estimated_vcount);

// For each slot in the draw order array of the skeleton
for (int s = 0; s < skeleton->slotsCount; ++s)
{
Expand Down Expand Up @@ -176,9 +210,6 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
const float* uvs = regionAttachment->uvs;

EnsureArrayFitsNumber(scratch, 4*2);
EnsureArrayFitsNumber(vertex_buffer, 6);

float colorR = tintR * regionAttachment->color.r;
float colorG = tintG * regionAttachment->color.g;
float colorB = tintB * regionAttachment->color.b;
Expand All @@ -199,21 +230,14 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
addVertex(&vertex_buffer[vindex++], scratch[4], scratch[5], uvs[4], uvs[5], colorR, colorG, colorB, colorA);
addVertex(&vertex_buffer[vindex++], scratch[6], scratch[7], uvs[6], uvs[7], colorR, colorG, colorB, colorA);
addVertex(&vertex_buffer[vindex++], scratch[0], scratch[1], uvs[0], uvs[1], colorR, colorG, colorB, colorA);

scratch.SetSize(0);
}
else if (attachment->type == SP_ATTACHMENT_MESH)
{
// Cast to an spMeshAttachment so we can get the rendererObject
// and compute the world vertices
spMeshAttachment* mesh = (spMeshAttachment*)attachment;

int num_world_vertices = mesh->super.worldVerticesLength / 2;

EnsureArrayFitsNumber(scratch, num_world_vertices*2);

int num_tri_vertices = mesh->trianglesCount; // It's a list of indices, where each 3-tuple define a triangle
EnsureArrayFitsNumber(vertex_buffer, num_tri_vertices);
int num_world_vertices = SUPER(mesh)->worldVerticesLength / 2;

// Computed the world vertices positions for the vertices that make up
// the mesh attachment. This assumes the world transform of the
Expand Down Expand Up @@ -241,10 +265,9 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto

addVertex(&vertex_buffer[vindex++], scratch[index], scratch[index + 1], uvs[index], uvs[index + 1], colorR, colorG, colorB, colorA);
}

scratch.SetSize(0);
}
}
scratch.SetSize(0);

const dmVMath::Matrix4& w = world;

Expand All @@ -260,6 +283,8 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
vertex->y = p.getY();
vertex->z = p.getZ();
}

assert(vcount == estimated_vcount);
}

return vcount;
Expand Down
1 change: 1 addition & 0 deletions defold-spine/include/common/vertices.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct SpineModelBounds
float maxY;
};

uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_triangle_count);
uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world);
void GetSkeletonBounds(const spSkeleton* skeleton, SpineModelBounds& bounds);

Expand Down
16 changes: 14 additions & 2 deletions defold-spine/src/comp_spine_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,18 @@ namespace dmSpine

uint32_t vertex_start = world->m_VertexBufferData.Size();
uint32_t vertex_count = 0;

for (uint32_t *i = begin; i != end; ++i)
{
component_index = (uint32_t)buf[*i].m_UserData;
const SpineModelComponent* component = (const SpineModelComponent*) components[component_index];
vertex_count += dmSpine::CalcVertexBufferSize(component->m_SkeletonInstance, 0);
}

if (vertex_count > world->m_VertexBufferData.Capacity())
world->m_VertexBufferData.SetCapacity(vertex_count);

vertex_count = 0;
for (uint32_t *i = begin; i != end; ++i)
{
component_index = (uint32_t)buf[*i].m_UserData;
Expand Down Expand Up @@ -860,7 +872,7 @@ namespace dmSpine
{
case dmRender::RENDER_LIST_OPERATION_BEGIN:
{
dmGraphics::SetVertexBufferData(world->m_VertexBuffer, 0, 0, dmGraphics::BUFFER_USAGE_STATIC_DRAW);
dmGraphics::SetVertexBufferData(world->m_VertexBuffer, 0, 0, dmGraphics::BUFFER_USAGE_DYNAMIC_DRAW);
world->m_RenderObjects.SetSize(0);
world->m_VertexBufferData.SetSize(0);
break;
Expand All @@ -873,7 +885,7 @@ namespace dmSpine
case dmRender::RENDER_LIST_OPERATION_END:
{
dmGraphics::SetVertexBufferData(world->m_VertexBuffer, sizeof(dmSpine::SpineVertex) * world->m_VertexBufferData.Size(),
world->m_VertexBufferData.Begin(), dmGraphics::BUFFER_USAGE_STATIC_DRAW);
world->m_VertexBufferData.Begin(), dmGraphics::BUFFER_USAGE_DYNAMIC_DRAW);
//DM_COUNTER("SpineVertexBuffer", world->m_VertexBufferData.Size() * sizeof(dmSpine::SpineVertex));
break;
}
Expand Down

0 comments on commit 0eb81dd

Please sign in to comment.