mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
On hardware the GE stops at every SIGNAL and FINISH, and it's the interrupt that gets it going again: on the same list after a signal, on the next one after a FINISH - once the finish callback has run, with the finished list still at the head of the queue. We ran the next list right away and dropped the finished one at once, so a finish callback saw an empty queue. A list enqueued from there was started instead of queued, and then couldn't be dequeued, which hung the new gpu/ge/queue2 test. ProcessDLQueue() now runs nothing while the head of the queue has an interrupt pending, and InterruptEnd() is what takes a finished list off the queue. This also keeps a stall update from restarting a list that's stopped at a signal before the handler has run. drawCompleteTicks is still set when the last list reaches its FINISH, so a sceGeDrawSync in between doesn't wait. Other things gpu/ge/queue2 and gpu/ge/breakwait showed, all from a real PSP: - sceGeListEnQueue compares against the address a list was enqueued with (or stopped at by sceGeBreak), mirrors included, not against its current pc. We had that the wrong way around. - The stack-in-use check only applies to lists that have started executing. This is probably what IgnoreEnqueue was added for (Metal Gear Acid 2, #10906). The flag stays until someone has checked the game without it. - A PAUSE signal makes the list PAUSED at once, before the FINISH delivers it. In between, sceGeContinue and sceGeBreak say BUSY, and updating the stall address does nothing, so a list that stalls there is stuck. - A completed list can't be dequeued, with or without a context. - sceGeDrawSync(1) looked at currentList instead of the list it had found. - sceGeBreak(1) doesn't wake anyone, and a late interrupt for a list it reset no longer marks that list completed. Threads in sceGeDrawSync are woken before the ones waiting for the last list. Also fixes currentList being lost when loading a state where it's list 0, and makes ge_pending_cb a plain std::list - nothing else touches it, and the GPU thread it was shared with is long gone. Same savestate format. See docs/sceGe.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>