Skip to content

fix(gum): create the VFPU context in whichever gum function runs first - #207

Open
ItsNoHax wants to merge 1 commit into
overdrivenpotato:masterfrom
ItsNoHax:fix-gum-cold-vfpu-context
Open

fix(gum): create the VFPU context in whichever gum function runs first#207
ItsNoHax wants to merge 1 commit into
overdrivenpotato:masterfrom
ItsNoHax:fix-gum-cold-vfpu-context

Conversation

@ItsNoHax

Copy link
Copy Markdown

Fixes #189.

The bug

VFPU_CONTEXT is created by sceGumLoadIdentity and sceGumLoadMatrix only. Every other gum
function reaches it through get_context_unchecked, which resolves a None context with
core::intrinsics::unreachable. Opening with any of them is undefined behaviour, and on a
debug build it traps:

E CPU: CPU exception: break instruction hit at 0881ad9c [ci_tests.text+16d9c]
psp::sys::gum::get_context_unchecked [ci_tests.text+16d2c]
sceGumMatrixMode [ci_tests.text+16e6c]

That is the report's sceGumMatrixMode failure exactly. It is easy to hit because
sceGumMatrixMode is what most setup code calls first — as in the issue's tutorial, which selects
a matrix mode before loading anything into it.

The fix

get_context_unchecked becomes get_context, which creates the context on demand, and the two
functions that were doing that inline now go through it too. Creating a Context is a zeroed
matrix set with an empty saved mask, so doing it from any entry point is the same work
sceGumLoadIdentity already did — the choice of which function got to do it was arbitrary.

Tests

One case in ci/tests: open with sceGumMatrixMode on a cold context, then build a translation
and read it back with sceGumStoreMatrix to show the context it created is usable. No rendering,
so it needs no GU.

Only the first gum call in a process is cold, so there is one case to be had and it has to run
before the rest of the suite — hence its slot at the head of the list in main.rs.

Before (master, a8be764) the run stops at the cold call and never reaches a final token, so
run-tests.sh fails on the missing FINAL_SUCCESS:

STARTING_TESTS

After:

STARTING_TESTS
[PASS]: (gum_cold_matrix_mode) (1.0, 2.0, 3.0) == (1.0, 2.0, 3.0)
...
FINAL_SUCCESS

Run with PPSSPPHeadless ... --timeout=40 -r . as ci/concourse/run-tests.sh does. The rest of
the suite is unaffected and cargo fmt is clean for both psp and ci/tests.

Note

This is independent of #206, which is a separate bug in sceGumPushMatrix. Both add a test module,
so if one lands first the other needs a trivial rebase on the mod and array lines in
ci/tests/src/main.rs. The test here deliberately avoids push/pop so it passes on master's stack
behaviour.

Only `sceGumLoadIdentity` and `sceGumLoadMatrix` created `VFPU_CONTEXT`. Every
other gum function went through `get_context_unchecked`, which resolved a `None`
context with `core::intrinsics::unreachable`. Opening with any of them -- most
naturally `sceGumMatrixMode`, which is the first call in most setup code -- is
therefore undefined behaviour, and in practice traps:

    E CPU: CPU exception: break instruction hit at 0881ad9c
    psp::sys::gum::get_context_unchecked
    sceGumMatrixMode

Replace the helper with `get_context`, which creates the context on demand, and
use it everywhere including the two functions that previously did this inline.
The context is a zeroed matrix set with no saved registers, so creating it from
any entry point is the same work `sceGumLoadIdentity` was already doing.

Adds a regression test to ci/tests that opens with `sceGumMatrixMode` and reads
the resulting matrix back. It has to run first, since only the first gum call in
a process is cold. Against master the run stops after STARTING_TESTS with no
final token; with this change the suite ends FINAL_SUCCESS.

Fixes overdrivenpotato#189.
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.

VFPU_CONTEXT might not be initialized for further gum calls

1 participant