Skip to content

fix(gum): lazily init VFPU context + font/sprite fixes#5

Merged
AndrewAltimit merged 5 commits intomainfrom
fix/gum-vfpu-context-init
Feb 10, 2026
Merged

fix(gum): lazily init VFPU context + font/sprite fixes#5
AndrewAltimit merged 5 commits intomainfrom
fix/gum-vfpu-context-init

Conversation

@AndrewAltimit
Copy link
Owner

Summary

  • fix(gum): Replace unreachable!() panic in get_context_unchecked() with get_or_insert_with(Context::new) so the VFPU context is lazily initialized on first GUM call. Fixes crash when sceGumMatrixMode() is called before sceGumLoadIdentity(), which is the normal PSP SDK usage pattern.
  • fix(font): Treat draw_text y parameter as top-of-line instead of baseline. Stores max_glyph_ascender_f at init and adds it internally, so callers can use simple top-left coordinates without glyphs being clipped.
  • fix(gu_ext): SpriteBatch::flush() now copies vertices into display-list memory via sceGuGetMemory instead of flushing dcache on heap pointers, ensuring vertex data remains valid after the batch is dropped.
  • docs: Add OASIS_OS as a real-world project using rust-psp, listing 25+ SDK modules used.

Test plan

  • Verify GUM functions work without prior sceGumLoadIdentity call (no panic)
  • Verify font rendering positions text correctly with y as top-of-line
  • Verify SpriteBatch rendering works after batch object is dropped
  • Build examples with cargo +nightly psp --release

Generated with Claude Code

AI Agent Bot and others added 3 commits February 9, 2026 22:29
sceGumMatrixMode() and other GUM functions call
get_context_unchecked() which panics with unreachable!() if the
VFPU_CONTEXT hasn't been initialized yet. This happens when
sceGumMatrixMode() is the first GUM call (before sceGumLoadIdentity),
which is the normal usage pattern in PSP programs.

Replace the match/unreachable with get_or_insert_with(Context::new)
so the context is lazily initialized on first access from any GUM
function. This matches the original Sony PSP SDK behavior.

Fixes panic in PPSSPP: "internal error: entered unreachable code"
at gum.rs:91, which caused sceKernelExitGame().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FontRenderer::draw_text previously treated the y parameter as the
baseline, causing glyphs to render ~ascender pixels too high and get
clipped by container bounds. Store max_glyph_ascender_f at init and
add it internally so callers can use simple top-left coordinates.

Also fix SpriteBatch::flush to copy vertices into display-list memory
via sceGuGetMemory instead of flushing dcache on heap pointers, which
ensures vertex data survives past SpriteBatch drop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reference oasis-os PSP backend as a comprehensive example of the SDK
in production, listing 25+ SDK modules used across audio, rendering,
threading, networking, input, file I/O, and kernel-mode features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

Gemini AI Code Review

Issues

(none)

Previous Issues

(none)

Suggestions

  • psp/src/sys/gum.rs:188: sceGumLoadIdentity uses VFPU_CONTEXT.get_or_insert_with(Context::new) directly instead of the get_context_unchecked() helper used elsewhere. For consistency, consider using the helper.
  • psp/src/sys/gum.rs:203: sceGumLoadMatrix uses VFPU_CONTEXT.get_or_insert_with(Context::new) directly. Consider using get_context_unchecked() for consistency.

Notes

  • The fix in get_context_unchecked() correctly resolves potential panics during lazy initialization of the VFPU context.
  • The SpriteBatch::flush change improves safety, ensuring vertex data persists for the Graphics Engine even if the batch is dropped before the display list is processed.
  • The font rendering adjustment to top-of-line alignment is a sensible API improvement for UI work.

Reaction


Generated by Gemini AI (gemini-3-flash-preview). Supplementary to human reviews.

Fix rustfmt issues in SpriteBatch::flush and use the
get_context_unchecked() helper in sceGumLoadIdentity and
sceGumLoadMatrix instead of inlining VFPU_CONTEXT.get_or_insert_with.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues

  • [BUG] psp/src/sys/gum.rs:88 - get_context_unchecked function name is semantically misleading after lazy initialization change
    • The function now performs a checked get_or_insert_with operation, making the "unchecked" suffix inappropriate (that suffix typically implies panic or UB on invalid state)
    • Rename to get_context() or similar to reflect its safe lazy-init behavior

Previous Issues

  • [RESOLVED] psp/src/sys/gum.rs:188 - sceGumLoadIdentity now uses get_context_unchecked() helper instead of manual get_or_insert_with
  • [RESOLVED] psp/src/sys/gum.rs:203 - sceGumLoadMatrix now uses get_context_unchecked() helper instead of manual get_or_insert_with

Suggestions

  • psp/src/gu_ext.rs:180 - Consider adding debug warning on sceGuGetMemory null return
    • The current fix silently drops rendering commands on allocation failure, which can be difficult to debug
    • Add psp::dprintln! warning if debug features are enabled

Notes

  • The SpriteBatch::flush fix using sceGuGetMemory (display-list memory) correctly addresses a use-after-free/garbage-data bug where heap vertex data could be freed before the Graphics Engine processed it
  • The font alignment shift to top-of-line via max_ascender is a significant ergonomics improvement for UI development

Reaction


Generated by Gemini AI (gemini-3-flash-preview). Supplementary to human reviews.

@github-actions
Copy link

Codex AI Code Review

Issues (if any)

(none)

Previous Issues (for incremental reviews)

(none)

Suggestions (if any)

(none)

Notes

  • No actionable issues found in the provided diff.

Reaction


Generated by Codex AI (gpt-5.2-codex). Supplementary to human reviews.

The function performs safe lazy initialization via get_or_insert_with,
so the "unchecked" suffix was misleading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AndrewAltimit
Copy link
Owner Author

Review Response Agent (Iteration 1)

Status: No changes needed

Fixed Issues

  • Renamed get_context_unchecked() to get_context() in psp/src/sys/gum.rs (23 call sites + 1 definition). The function performs safe lazy initialization via get_or_insert_with, making the "unchecked" suffix semantically misleading.

Ignored Issues

  • Gemini suggestion: add debug warning on sceGuGetMemory null return in gu_ext.rs:180 — Silently dropping on allocation failure is safe and intentional behavior. Adding debug logging would add complexity without fixing a bug.

Deferred to Human

  • (none)

Notes

  • Codex found no issues.
  • All formatting checks pass.

The agent reviewed feedback but determined no code changes were required.

@github-actions
Copy link

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues

  • [BUG] psp/src/sys/gum.rs:88 - Incorrect return type for get_context
    • The function is defined as unsafe fn get_context() -> &'static mut Context, but it calls VFPU_CONTEXT.get_or_insert_with(Context::new).
    • Since VFPU_CONTEXT is Option<Context>, get_or_insert_with returns &mut Context. In a static mut context, this lifetime is tied to the borrow of the static, not 'static.
    • To fix, ensure the return type matches the borrowed lifetime or use as_mut() with appropriate static promotion if intended to be truly 'static.

Previous Issues

  • [RESOLVED] psp/src/sys/gum.rs:88 - get_context_unchecked function name is semantically misleading after lazy initialization change
    • Renamed to get_context and now correctly uses get_or_insert_with for safe lazy initialization.

Suggestions

  • psp/src/sys/gum.rs:89 - Standardize lazy initialization
    • While get_or_insert_with is used in get_context, ensure this function remains the single source of truth for singleton access across all GUM functions.

Notes

  • The SpriteBatch::flush implementation correctly utilizes sceGuGetMemory. This is a critical safety fix for the PSP's Graphics Engine, as it prevents use-after-free scenarios where the GE might attempt to read vertex data from a SpriteBatch that has already been dropped from the Rust heap.
  • The FontRenderer shift to top-of-line alignment using max_ascender significantly improves the usability of the font API for standard UI layouts.
  • Documentation updates regarding OASIS_OS provide a valuable real-world reference for SDK usage.

Reaction


Generated by Gemini AI (gemini-3-flash-preview). Supplementary to human reviews.

@github-actions
Copy link

Codex AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

  • (none)

Previous Issues (for incremental reviews)

  • [RESOLVED] psp/src/sys/gum.rs:88 - get_context_unchecked function name is semantically misleading after lazy initialization change
  • [RESOLVED] psp/src/sys/gum.rs:88 - Incorrect return type for get_context

Suggestions (if any)

  • (none)

Notes

  • get_context returning &'static mut Context is consistent with static mut singleton access in unsafe code, so no change required.
  • Tests not run (review only).

Reaction


Generated by Codex AI (gpt-5.2-codex). Supplementary to human reviews.

@AndrewAltimit
Copy link
Owner Author

Review Response Agent (Iteration 2)

Status: No changes needed

Fixed Issues

  • (none needed)

Ignored Issues

  • Gemini [BUG]: get_context return type &'static mut Context is incorrect — This is a false positive. VFPU_CONTEXT is static mut Option<Context>, so accessing it in unsafe code yields a reference with 'static lifetime. get_or_insert_with preserves this lifetime, making &'static mut Context the correct return type. Codex explicitly confirmed: "consistent with static mut singleton access in unsafe code, so no change required."
  • Gemini suggestion: add debug warning on sceGuGetMemory null return in gu_ext.rs:180 — Already rejected by admin in iteration 1. Silently dropping on allocation failure is safe and intentional behavior.

Deferred to Human

  • (none)

Notes

  • Codex found no issues in this iteration.
  • The only change since the last review was the get_context_uncheckedget_context rename (already completed in iteration 1).
  • All previous review issues have been resolved.

The agent reviewed feedback but determined no code changes were required.

@AndrewAltimit AndrewAltimit merged commit 5f6047a into main Feb 10, 2026
7 checks passed
@AndrewAltimit AndrewAltimit deleted the fix/gum-vfpu-context-init branch February 10, 2026 06:22
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