Skip to content

Fix text corruption in oversized labels (16-bit text index overflow)#19

Open
Schogol wants to merge 1 commit into
carbonengine:mainfrom
Schogol:fix/text-index-count-16bit-overflow
Open

Fix text corruption in oversized labels (16-bit text index overflow)#19
Schogol wants to merge 1 commit into
carbonengine:mainfrom
Schogol:fix/text-index-count-16bit-overflow

Conversation

@Schogol

@Schogol Schogol commented Jul 4, 2026

Copy link
Copy Markdown

Summary

Popup windows with a very large amount of text (e.g. contract confirmations with many items, "can't activate" acceleration-gate messages) render corrupt. The text sprite batch used 16-bit indices, which overflow once a single label exceeds 65,535 indices.

Should fix EDR-1989.

Root cause

EVE's font emits 2 quads per glyph = 12 indices/glyph with Text Shadow on, so a single label overflows the 16-bit index space at 65,535 / 12, i.e. about 5,461 visible glyphs. Two 16-bit bottlenecks:

  1. Index count: RenderTriangleVerts / EnsureBufferSpace / CopyIndicesWithOffset / GrowCaptureIndexBuffer took unsigned short indexCount, truncating the unsigned int count the font passes (the ~5,461-glyph limit).
  2. Index values: Tr2FontMeasurer::m_indices was unsigned short, so per-draw-call vertex indices wrap once a single-texture run exceeds 65,535 vertices (~8,191 glyphs with shadow).

UI text goes through the capture/display-list path, which does not split batches, so the whole label hits these 16-bit boundaries in one submission.

Fix

Widen the text sprite index path to 32-bit:

  • Index counts unsigned short -> unsigned int in RenderTriangleVerts (both overloads), EnsureBufferSpace, CopyIndicesWithOffset, GrowCaptureIndexBuffer.
  • Index values in Tr2FontMeasurer (m_indices, AdjustIndicesIfNeeded) -> unsigned int, submitted via new 32-bit RenderTriangleVerts / CopyIndicesWithOffset overloads. The existing 16-bit overloads are kept for the other sprite types (frames, lines, brackets) that pass 16-bit index arrays, so their callers are untouched.

The GPU index buffer is already 32-bit (m_indexBuffer.Create(indexCount, 4)), so no GPU format change is needed; this only stops the CPU-side truncation before the data reaches the already-32-bit buffer.

Text sprite batches used 16-bit index counts and 16-bit index values, so
a single label overflowed once its geometry exceeded 65535 indices:
2 quads/glyph = 12 indices/glyph with Text Shadow, i.e. ~5461 visible
glyphs. Past that, the index count wrapped (and beyond ~8191 glyphs the
per-draw-call vertex index values wrapped too), corrupting the render of
large popups such as contracts and acceleration-gate messages.

Widen the sprite index path to 32-bit:
- RenderTriangleVerts / EnsureBufferSpace / CopyIndicesWithOffset /
  GrowCaptureIndexBuffer index counts unsigned short -> unsigned int
- Tr2FontMeasurer index values (m_indices, AdjustIndicesIfNeeded) to
  unsigned int, submitted via new 32-bit RenderTriangleVerts /
  CopyIndicesWithOffset overloads so the existing 16-bit path used by
  other sprite types is untouched

The GPU index buffer is already 32-bit (stride 4), so no format change
is needed. Relates to EDR-1989.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant