Skip to content

Commit 7aed73f

Browse files
committed
(d3d11) d3d11_font_render_line optimizations:
* use function pointer for repeated get_glyph calls * Pointer-walk main loop * Reciprocal precomputation * Map() error check * count computed from local v_start
1 parent f580b39 commit 7aed73f

File tree

1 file changed

+70
-44
lines changed

1 file changed

+70
-44
lines changed

gfx/drivers/d3d11.c

Lines changed: 70 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,30 +1079,45 @@ static void d3d11_font_render_line(
10791079
unsigned height,
10801080
unsigned text_align)
10811081
{
1082-
size_t i;
10831082
unsigned count;
10841083
D3D11_MAPPED_SUBRESOURCE mapped_vbo;
1084+
HRESULT hr;
10851085
const char* msg_end = msg + msg_len;
10861086
d3d11_sprite_t *v = NULL;
10871087
int x = pre_x;
1088-
int y = roundf((1.0 - pos_y) * height);
1089-
1088+
int y = roundf((1.0f - pos_y) * height);
1089+
1090+
/* Hoist function pointer and data pointer out of the loop to avoid
1091+
* repeated dependent loads through font->font_driver->get_glyph. */
1092+
const struct font_glyph* (*get_glyph)(void*, uint32_t)
1093+
= font->font_driver->get_glyph;
1094+
void *font_data = font->font_data;
1095+
1096+
/* Precompute reciprocals -- replaces 8 per-glyph divisions with
1097+
* multiplications (~3-5x faster per op on most hardware). */
1098+
const float inv_vp_w = 1.0f / (float)d3d11->viewport.Width;
1099+
const float inv_vp_h = 1.0f / (float)d3d11->viewport.Height;
1100+
const float inv_tex_w = 1.0f / (float)font->texture.desc.Width;
1101+
const float inv_tex_h = 1.0f / (float)font->texture.desc.Height;
1102+
1103+
/* msg_len is byte length, which is >= the actual glyph count for
1104+
* multi-byte UTF-8 sequences. This makes the capacity check
1105+
* conservatively safe. */
10901106
if (d3d11->sprites.offset + msg_len > (unsigned)d3d11->sprites.capacity)
10911107
d3d11->sprites.offset = 0;
10921108

10931109
/* For right/center alignment, compute width with a lightweight pass
1094-
* that only accumulates advance_x avoids the redundant glyph lookups
1110+
* that only accumulates advance_x -- avoids the redundant glyph lookups
10951111
* and atlas dirty checks that d3d11_font_get_message_width would repeat. */
10961112
if (text_align == TEXT_ALIGN_RIGHT || text_align == TEXT_ALIGN_CENTER)
10971113
{
1098-
int width_accum = 0;
1099-
const char *scan = msg;
1100-
const char *scan_end = msg_end;
1101-
while (scan < scan_end)
1114+
int width_accum = 0;
1115+
const char *scan = msg;
1116+
while (scan < msg_end)
11021117
{
11031118
const struct font_glyph *glyph;
11041119
uint32_t code = utf8_walk(&scan);
1105-
if (!(glyph = font->font_driver->get_glyph(font->font_data, code)))
1120+
if (!(glyph = get_glyph(font_data, code)))
11061121
if (!(glyph = glyph_q))
11071122
continue;
11081123
width_accum += glyph->advance_x;
@@ -1114,51 +1129,59 @@ static void d3d11_font_render_line(
11141129
x -= (int)(width_accum * scale) / 2;
11151130
}
11161131

1117-
d3d11->context->lpVtbl->Map(
1118-
d3d11->context, (D3D11Resource)d3d11->sprites.vbo, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo);
1132+
hr = d3d11->context->lpVtbl->Map(
1133+
d3d11->context, (D3D11Resource)d3d11->sprites.vbo,
1134+
0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped_vbo);
1135+
1136+
if (FAILED(hr))
1137+
return;
1138+
11191139
v = (d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset;
11201140

1121-
for (i = 0; i < msg_len; i++)
1141+
/* Walk the string by pointer using utf8_walk -- cleaner and faster than
1142+
* the old byte-index loop with manual skip adjustment. */
11221143
{
1123-
const struct font_glyph* glyph;
1124-
const char *msg_tmp= &msg[i];
1125-
unsigned code = utf8_walk(&msg_tmp);
1126-
unsigned skip = msg_tmp - &msg[i];
1144+
const char *scan = msg;
1145+
d3d11_sprite_t *v_start = v;
11271146

1128-
if (skip > 1)
1129-
i += skip - 1;
1147+
while (scan < msg_end)
1148+
{
1149+
const struct font_glyph *glyph;
1150+
uint32_t code = utf8_walk(&scan);
11301151

1131-
/* Do something smarter here ... */
1132-
if (!(glyph = font->font_driver->get_glyph(font->font_data, code)))
1133-
if (!(glyph = glyph_q))
1134-
continue;
1152+
if (!(glyph = get_glyph(font_data, code)))
1153+
if (!(glyph = glyph_q))
1154+
continue;
11351155

1136-
v->pos.x = (x + (glyph->draw_offset_x * scale)) / (float)d3d11->viewport.Width;
1137-
v->pos.y = (y + (glyph->draw_offset_y * scale)) / (float)d3d11->viewport.Height;
1138-
v->pos.w = glyph->width * scale / (float)d3d11->viewport.Width;
1139-
v->pos.h = glyph->height * scale / (float)d3d11->viewport.Height;
1156+
v->pos.x = (x + (glyph->draw_offset_x * scale)) * inv_vp_w;
1157+
v->pos.y = (y + (glyph->draw_offset_y * scale)) * inv_vp_h;
1158+
v->pos.w = glyph->width * scale * inv_vp_w;
1159+
v->pos.h = glyph->height * scale * inv_vp_h;
11401160

1141-
v->coords.u = glyph->atlas_offset_x / (float)font->texture.desc.Width;
1142-
v->coords.v = glyph->atlas_offset_y / (float)font->texture.desc.Height;
1143-
v->coords.w = glyph->width / (float)font->texture.desc.Width;
1144-
v->coords.h = glyph->height / (float)font->texture.desc.Height;
1161+
v->coords.u = glyph->atlas_offset_x * inv_tex_w;
1162+
v->coords.v = glyph->atlas_offset_y * inv_tex_h;
1163+
v->coords.w = glyph->width * inv_tex_w;
1164+
v->coords.h = glyph->height * inv_tex_h;
11451165

1146-
v->params.scaling = 1;
1147-
v->params.rotation = 0;
1166+
v->params.scaling = 1;
1167+
v->params.rotation = 0;
11481168

1149-
v->colors[0] = color;
1150-
v->colors[1] = color;
1151-
v->colors[2] = color;
1152-
v->colors[3] = color;
1169+
v->colors[0] = color;
1170+
v->colors[1] = color;
1171+
v->colors[2] = color;
1172+
v->colors[3] = color;
11531173

1154-
v++;
1174+
v++;
1175+
1176+
x += glyph->advance_x * scale;
1177+
y += glyph->advance_y * scale;
1178+
}
11551179

1156-
x += glyph->advance_x * scale;
1157-
y += glyph->advance_y * scale;
1180+
count = (unsigned)(v - v_start);
11581181
}
11591182

1160-
count = v - ((d3d11_sprite_t*)mapped_vbo.pData + d3d11->sprites.offset);
1161-
d3d11->context->lpVtbl->Unmap(d3d11->context, (D3D11Resource)d3d11->sprites.vbo, 0);
1183+
d3d11->context->lpVtbl->Unmap(
1184+
d3d11->context, (D3D11Resource)d3d11->sprites.vbo, 0);
11621185

11631186
if (!count)
11641187
return;
@@ -1184,9 +1207,12 @@ static void d3d11_font_render_line(
11841207
d3d11->context->lpVtbl->OMSetBlendState(d3d11->context, d3d11->blend_enable,
11851208
NULL, D3D11_DEFAULT_SAMPLE_MASK);
11861209

1187-
d3d11->context->lpVtbl->PSSetShader(d3d11->context, d3d11->sprites.shader_font.ps, NULL, 0);
1188-
d3d11->context->lpVtbl->Draw(d3d11->context, count, d3d11->sprites.offset);
1189-
d3d11->context->lpVtbl->PSSetShader(d3d11->context, d3d11->sprites.shader.ps, NULL, 0);
1210+
d3d11->context->lpVtbl->PSSetShader(
1211+
d3d11->context, d3d11->sprites.shader_font.ps, NULL, 0);
1212+
d3d11->context->lpVtbl->Draw(
1213+
d3d11->context, count, d3d11->sprites.offset);
1214+
d3d11->context->lpVtbl->PSSetShader(
1215+
d3d11->context, d3d11->sprites.shader.ps, NULL, 0);
11901216

11911217
d3d11->sprites.offset += count;
11921218
}

0 commit comments

Comments
 (0)