Skip to content

Commit 802852c

Browse files
committed
Improve performance by using indexed drawing to draw quads
- Reduces memory footprint by 33% - Reduces number of vertex shader executions by 33% (vertex cache!) - Reduces CPU time spent emitting duplicate vertices
1 parent 7f784c8 commit 802852c

3 files changed

Lines changed: 76 additions & 38 deletions

File tree

source/base.c

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ C2Di_Context __C2Di_Context;
55
static C3D_Mtx s_projTop, s_projBot;
66
static int uLoc_mdlvMtx, uLoc_projMtx;
77

8+
static inline bool C2Di_CheckBufSpace(C2Di_Context* ctx, unsigned idx, unsigned vtx)
9+
{
10+
size_t free_idx = ctx->idxBufSize - ctx->idxBufPos;
11+
size_t free_vtx = ctx->vtxBufSize - ctx->vtxBufPos;
12+
return free_idx >= idx && free_vtx >= vtx;
13+
}
14+
815
static void C2Di_FrameEndHook(void* unused)
916
{
1017
C2Di_Context* ctx = C2Di_GetContext();
1118
C2Di_FlushVtxBuf();
1219
ctx->vtxBufPos = 0;
13-
ctx->vtxBufLastPos = 0;
20+
ctx->idxBufPos = 0;
21+
ctx->idxBufLastPos = 0;
1422
}
1523

1624
bool C2D_Init(size_t maxObjects)
@@ -19,14 +27,23 @@ bool C2D_Init(size_t maxObjects)
1927
if (ctx->flags & C2DiF_Active)
2028
return false;
2129

22-
ctx->vtxBufSize = 6*maxObjects;
30+
ctx->vtxBufSize = 4*maxObjects;
2331
ctx->vtxBuf = (C2Di_Vertex*)linearAlloc(ctx->vtxBufSize*sizeof(C2Di_Vertex));
2432
if (!ctx->vtxBuf)
2533
return false;
2634

35+
ctx->idxBufSize = 6*maxObjects;
36+
ctx->idxBuf = (u16*)linearAlloc(ctx->idxBufSize*sizeof(u16));
37+
if (!ctx->idxBuf)
38+
{
39+
linearFree(ctx->vtxBuf);
40+
return false;
41+
}
42+
2743
ctx->shader = DVLB_ParseFile((u32*)render2d_shbin, render2d_shbin_size);
2844
if (!ctx->shader)
2945
{
46+
linearFree(ctx->idxBuf);
3047
linearFree(ctx->vtxBuf);
3148
return false;
3249
}
@@ -75,7 +92,8 @@ bool C2D_Init(size_t maxObjects)
7592

7693
ctx->flags = C2DiF_Active | (C2DiF_Mode_ImageSolid << (C2DiF_TintMode_Shift-C2DiF_Mode_Shift));
7794
ctx->vtxBufPos = 0;
78-
ctx->vtxBufLastPos = 0;
95+
ctx->idxBufPos = 0;
96+
ctx->idxBufLastPos = 0;
7997
Mtx_Identity(&ctx->projMtx);
8098
Mtx_Identity(&ctx->mdlvMtx);
8199
ctx->fadeClr = 0;
@@ -94,6 +112,7 @@ void C2D_Fini(void)
94112
C3D_FrameEndHook(NULL, NULL);
95113
shaderProgramFree(&ctx->program);
96114
DVLB_Free(ctx->shader);
115+
linearFree(ctx->idxBuf);
97116
linearFree(ctx->vtxBuf);
98117
}
99118

@@ -370,7 +389,7 @@ bool C2D_DrawImage(C2D_Image img, const C2D_DrawParams* params, const C2D_ImageT
370389
C2Di_Context* ctx = C2Di_GetContext();
371390
if (!(ctx->flags & C2DiF_Active))
372391
return false;
373-
if (6 > (ctx->vtxBufSize - ctx->vtxBufPos))
392+
if (!C2Di_CheckBufSpace(ctx, 6, 4))
374393
return false;
375394

376395
C2Di_SetMode((ctx->flags & C2DiF_TintMode_Mask) >> (C2DiF_TintMode_Shift - C2DiF_Mode_Shift));
@@ -407,15 +426,11 @@ bool C2D_DrawImage(C2D_Image img, const C2D_DrawParams* params, const C2D_ImageT
407426
const C2D_Tint* tintBotLeft = tint ? &tint->corners[C2D_BotLeft] : &s_defaultTint;
408427
const C2D_Tint* tintBotRight = tint ? &tint->corners[C2D_BotRight] : &s_defaultTint;
409428

410-
// Draw triangles
429+
C2Di_AppendQuad();
411430
C2Di_AppendVtx(quad.topLeft[0], quad.topLeft[1], params->depth, tcTopLeft[0], tcTopLeft[1], 0, tintTopLeft->blend, tintTopLeft->color);
431+
C2Di_AppendVtx(quad.topRight[0], quad.topRight[1], params->depth, tcTopRight[0], tcTopRight[1], 0, tintTopRight->blend, tintTopRight->color);
412432
C2Di_AppendVtx(quad.botLeft[0], quad.botLeft[1], params->depth, tcBotLeft[0], tcBotLeft[1], 0, tintBotLeft->blend, tintBotLeft->color);
413433
C2Di_AppendVtx(quad.botRight[0], quad.botRight[1], params->depth, tcBotRight[0], tcBotRight[1], 0, tintBotRight->blend, tintBotRight->color);
414-
415-
C2Di_AppendVtx(quad.topLeft[0], quad.topLeft[1], params->depth, tcTopLeft[0], tcTopLeft[1], 0, tintTopLeft->blend, tintTopLeft->color);
416-
C2Di_AppendVtx(quad.botRight[0], quad.botRight[1], params->depth, tcBotRight[0], tcBotRight[1], 0, tintBotRight->blend, tintBotRight->color);
417-
C2Di_AppendVtx(quad.topRight[0], quad.topRight[1], params->depth, tcTopRight[0], tcTopRight[1], 0, tintTopRight->blend, tintTopRight->color);
418-
419434
return true;
420435
}
421436

@@ -424,12 +439,13 @@ bool C2D_DrawTriangle(float x0, float y0, u32 clr0, float x1, float y1, u32 clr1
424439
C2Di_Context* ctx = C2Di_GetContext();
425440
if (!(ctx->flags & C2DiF_Active))
426441
return false;
427-
if (3 > (ctx->vtxBufSize - ctx->vtxBufPos))
442+
if (!C2Di_CheckBufSpace(ctx, 3, 3))
428443
return false;
429444

430445
C2Di_SetMode(C2DiF_Mode_Solid);
431446
C2Di_Update();
432447

448+
C2Di_AppendTri();
433449
C2Di_AppendVtx(x0, y0, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
434450
C2Di_AppendVtx(x1, y1, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
435451
C2Di_AppendVtx(x2, y2, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr2);
@@ -441,7 +457,7 @@ bool C2D_DrawLine(float x0, float y0, u32 clr0, float x1, float y1, u32 clr1, fl
441457
C2Di_Context* ctx = C2Di_GetContext();
442458
if (!(ctx->flags & C2DiF_Active))
443459
return false;
444-
if (6 > (ctx->vtxBufSize - ctx->vtxBufPos))
460+
if (!C2Di_CheckBufSpace(ctx, 6, 4))
445461
return false;
446462

447463
float dx = x1-x0, dy = y1-y0, len = sqrtf(dx*dx+dy*dy), th = thickness/2;
@@ -451,13 +467,11 @@ bool C2D_DrawLine(float x0, float y0, u32 clr0, float x1, float y1, u32 clr1, fl
451467
C2Di_SetMode(C2DiF_Mode_Solid);
452468
C2Di_Update();
453469

470+
C2Di_AppendQuad();
454471
C2Di_AppendVtx(px0, py0, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
472+
C2Di_AppendVtx(px3, py3, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
455473
C2Di_AppendVtx(px1, py1, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
456474
C2Di_AppendVtx(px2, py2, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
457-
458-
C2Di_AppendVtx(px2, py2, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
459-
C2Di_AppendVtx(px3, py3, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
460-
C2Di_AppendVtx(px0, py0, depth, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
461475
return true;
462476
}
463477

@@ -466,19 +480,17 @@ bool C2D_DrawRectangle(float x, float y, float z, float w, float h, u32 clr0, u3
466480
C2Di_Context* ctx = C2Di_GetContext();
467481
if (!(ctx->flags & C2DiF_Active))
468482
return false;
469-
if (6 > (ctx->vtxBufSize - ctx->vtxBufPos))
483+
if (!C2Di_CheckBufSpace(ctx, 6, 4))
470484
return false;
471485

472486
C2Di_SetMode(C2DiF_Mode_Solid);
473487
C2Di_Update();
474488

489+
C2Di_AppendQuad();
475490
C2Di_AppendVtx(x, y, z, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
491+
C2Di_AppendVtx(x+w, y, z, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
476492
C2Di_AppendVtx(x, y+h, z, 0.0f, 0.0f, 0.0f, 0.0f, clr2);
477493
C2Di_AppendVtx(x+w, y+h, z, 0.0f, 0.0f, 0.0f, 0.0f, clr3);
478-
479-
C2Di_AppendVtx(x, y, z, 0.0f, 0.0f, 0.0f, 0.0f, clr0);
480-
C2Di_AppendVtx(x+w, y+h, z, 0.0f, 0.0f, 0.0f, 0.0f, clr3);
481-
C2Di_AppendVtx(x+w, y, z, 0.0f, 0.0f, 0.0f, 0.0f, clr1);
482494
return true;
483495
}
484496

@@ -487,22 +499,45 @@ bool C2D_DrawEllipse(float x, float y, float z, float w, float h, u32 clr0, u32
487499
C2Di_Context* ctx = C2Di_GetContext();
488500
if (!(ctx->flags & C2DiF_Active))
489501
return false;
490-
if (6 > (ctx->vtxBufSize - ctx->vtxBufPos))
502+
if (!C2Di_CheckBufSpace(ctx, 6, 4))
491503
return false;
492504

493505
C2Di_SetMode(C2DiF_Mode_Circle);
494506
C2Di_Update();
495507

508+
C2Di_AppendQuad();
496509
C2Di_AppendVtx(x, y, z, 0.0f, 0.0f, -1.0f, -1.0f, clr0);
510+
C2Di_AppendVtx(x+w, y, z, 0.0f, 0.0f, 1.0f, -1.0f, clr1);
497511
C2Di_AppendVtx(x, y+h, z, 0.0f, 0.0f, -1.0f, 1.0f, clr2);
498512
C2Di_AppendVtx(x+w, y+h, z, 0.0f, 0.0f, 1.0f, 1.0f, clr3);
499-
500-
C2Di_AppendVtx(x, y, z, 0.0f, 0.0f, -1.0f, -1.0f, clr0);
501-
C2Di_AppendVtx(x+w, y+h, z, 0.0f, 0.0f, 1.0f, 1.0f, clr3);
502-
C2Di_AppendVtx(x+w, y, z, 0.0f, 0.0f, 1.0f, -1.0f, clr1);
503513
return true;
504514
}
505515

516+
void C2Di_AppendTri(void)
517+
{
518+
C2Di_Context* ctx = C2Di_GetContext();
519+
u16* idx = &ctx->idxBuf[ctx->idxBufPos];
520+
ctx->idxBufPos += 3;
521+
522+
*idx++ = ctx->vtxBufPos+0;
523+
*idx++ = ctx->vtxBufPos+1;
524+
*idx++ = ctx->vtxBufPos+2;
525+
}
526+
527+
void C2Di_AppendQuad(void)
528+
{
529+
C2Di_Context* ctx = C2Di_GetContext();
530+
u16* idx = &ctx->idxBuf[ctx->idxBufPos];
531+
ctx->idxBufPos += 6;
532+
533+
*idx++ = ctx->vtxBufPos+0;
534+
*idx++ = ctx->vtxBufPos+2;
535+
*idx++ = ctx->vtxBufPos+1;
536+
*idx++ = ctx->vtxBufPos+1;
537+
*idx++ = ctx->vtxBufPos+2;
538+
*idx++ = ctx->vtxBufPos+3;
539+
}
540+
506541
void C2Di_AppendVtx(float x, float y, float z, float u, float v, float ptx, float pty, u32 color)
507542
{
508543
C2Di_Context* ctx = C2Di_GetContext();
@@ -520,10 +555,10 @@ void C2Di_AppendVtx(float x, float y, float z, float u, float v, float ptx, floa
520555
void C2Di_FlushVtxBuf(void)
521556
{
522557
C2Di_Context* ctx = C2Di_GetContext();
523-
size_t len = ctx->vtxBufPos - ctx->vtxBufLastPos;
558+
size_t len = ctx->idxBufPos - ctx->idxBufLastPos;
524559
if (!len) return;
525-
C3D_DrawArrays(GPU_TRIANGLES, ctx->vtxBufLastPos, len);
526-
ctx->vtxBufLastPos = ctx->vtxBufPos;
560+
C3D_DrawElements(GPU_TRIANGLES, len, C3D_UNSIGNED_SHORT, &ctx->idxBuf[ctx->idxBufLastPos]);
561+
ctx->idxBufLastPos = ctx->idxBufPos;
527562
}
528563

529564
void C2Di_Update(void)

source/internal.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ typedef struct
2222
u32 sceneW, sceneH;
2323

2424
C2Di_Vertex* vtxBuf;
25+
u16* idxBuf;
26+
2527
size_t vtxBufSize;
2628
size_t vtxBufPos;
27-
size_t vtxBufLastPos;
29+
30+
size_t idxBufSize;
31+
size_t idxBufPos;
32+
size_t idxBufLastPos;
2833

2934
u32 flags;
3035
C3D_Mtx projMtx;
@@ -103,6 +108,8 @@ typedef struct
103108
} C2Di_Quad;
104109

105110
void C2Di_CalcQuad(C2Di_Quad* quad, const C2D_DrawParams* params);
111+
void C2Di_AppendTri(void);
112+
void C2Di_AppendQuad(void);
106113
void C2Di_AppendVtx(float x, float y, float z, float u, float v, float ptx, float pty, u32 color);
107114
void C2Di_FlushVtxBuf(void);
108115
void C2Di_Update(void);

source/text.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,8 @@ void C2D_DrawText(const C2D_Text* text, u32 flags, float x, float y, float z, fl
414414

415415
C2Di_SetTex(cur->sheet);
416416
C2Di_Update();
417+
C2Di_AppendQuad();
417418
C2Di_AppendVtx(glyphX, glyphY, glyphZ, cur->texcoord.left, cur->texcoord.top, 0.0f, 1.0f, color);
418-
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
419-
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
420419
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
421420
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
422421
C2Di_AppendVtx(glyphX+glyphW, glyphY+glyphH, glyphZ, cur->texcoord.right, cur->texcoord.bottom, 0.0f, 1.0f, color);
@@ -446,9 +445,8 @@ void C2D_DrawText(const C2D_Text* text, u32 flags, float x, float y, float z, fl
446445

447446
C2Di_SetTex(cur->sheet);
448447
C2Di_Update();
448+
C2Di_AppendQuad();
449449
C2Di_AppendVtx(glyphX, glyphY, glyphZ, cur->texcoord.left, cur->texcoord.top, 0.0f, 1.0f, color);
450-
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
451-
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
452450
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
453451
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
454452
C2Di_AppendVtx(glyphX+glyphW, glyphY+glyphH, glyphZ, cur->texcoord.right, cur->texcoord.bottom, 0.0f, 1.0f, color);
@@ -479,9 +477,8 @@ void C2D_DrawText(const C2D_Text* text, u32 flags, float x, float y, float z, fl
479477

480478
C2Di_SetTex(cur->sheet);
481479
C2Di_Update();
480+
C2Di_AppendQuad();
482481
C2Di_AppendVtx(glyphX, glyphY, glyphZ, cur->texcoord.left, cur->texcoord.top, 0.0f, 1.0f, color);
483-
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
484-
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
485482
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
486483
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
487484
C2Di_AppendVtx(glyphX+glyphW, glyphY+glyphH, glyphZ, cur->texcoord.right, cur->texcoord.bottom, 0.0f, 1.0f, color);
@@ -552,9 +549,8 @@ void C2D_DrawText(const C2D_Text* text, u32 flags, float x, float y, float z, fl
552549

553550
C2Di_SetTex(cur->sheet);
554551
C2Di_Update();
552+
C2Di_AppendQuad();
555553
C2Di_AppendVtx(glyphX, glyphY, glyphZ, cur->texcoord.left, cur->texcoord.top, 0.0f, 1.0f, color);
556-
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
557-
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
558554
C2Di_AppendVtx(glyphX+glyphW, glyphY, glyphZ, cur->texcoord.right, cur->texcoord.top, 0.0f, 1.0f, color);
559555
C2Di_AppendVtx(glyphX, glyphY+glyphH, glyphZ, cur->texcoord.left, cur->texcoord.bottom, 0.0f, 1.0f, color);
560556
C2Di_AppendVtx(glyphX+glyphW, glyphY+glyphH, glyphZ, cur->texcoord.right, cur->texcoord.bottom, 0.0f, 1.0f, color);

0 commit comments

Comments
 (0)