ref:7a2a4ef8d62f2083e3ba68fb1d144aee46c88569

Perf: memcpy texture upload (2.5ms → 0.95ms per frame)

Profiling showed TerminalTexture.upload() was the bottleneck: - Before: per-pixel setPixelRGBA loop = 2.5ms for 984K pixels (15% frame budget) - After: MemoryUtil.memCopy to NativeImage backing memory = 0.95ms (5.7%) The remaining 0.95ms is the GL texture upload (texture.upload()) which is an irreducible GPU operation. Implementation: - NativeImageAccessor mixin exposes the private `pixels` field (native ptr) - TerminalTexture caches the pointer at construction - upload() does a single memcpy from the direct ByteBuffer to the NativeImage - Falls back to per-pixel loop for non-direct buffers Also: ScreenGroup caches min/max bounds in constructor (eliminates 6 stream pipelines per getSubRegion call per frame). Profiling data (4x3 grid, 1440x720 terminal): - pollPty: 0.01ms (negligible) - getPixelData (Rust render): 0.38ms - texture upload: 0.95ms (was 2.5ms) - Total per-frame terminal cost: ~1.3ms (was ~2.9ms) 46 GameTests + 52 Rust tests, all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SHA: 7a2a4ef8d62f2083e3ba68fb1d144aee46c88569
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-03-20 17:24
Parents: dad8d80
6 files changed +86 -33
Type
common/src/main/resources/alacrittymc.mixins.json +2 −1
@@ -3,7 +3,8 @@
"package": "io.fangorn.alacrittymc.mixin",
"compatibilityLevel": "JAVA_17",
"client": [
"KeyboardHandlerMixin"
"KeyboardHandlerMixin",
"NativeImageAccessor"
],
"injectors": {
"defaultRequire": 1