Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Fifo: Run/sync with the GPU on command processor register access #7214
In Dolphin, we don't emulate the CPU and GPU in lock-step, for performance reasons. The CPU drives events, with the GPU emulation being one of these events which is fired periodically. This is the behavior in single core mode. Dual-core mode is completely non-deterministic here, and runs whenever Fifo::RunGpu() is called. Thus, I am mainly concerned about single-core mode.
Due to the GPU only being run every 1000 cycles or so, to a game, if it polled the command processor registers (for example, the read pointer, or distance), the GPU would appear to be stalled. Testing would suggest this is what causes FIFO resets/unknown opcodes in games such as F-Zero GX, and Rogue Squadron 3.
To work around this, each time these registers are accessed, we run the GPU for its time quantum. This way, to a game, the GPU is making progress (as it would on the console). While this isn't necessarily accurate to the hardware in terms of cycles executed, we don't really emulate GPU timings anyway, so executing a few extra GPU cycles doesn't really have any impact.
In dual core, it syncs with the GPU thread, and ensures that the GPU thread isn't too far behind. Again, this is not deterministic, but dual core isn't to begin with, and has numerous stability issues as a result.
Long-term, I'm planning on refactoring the FIFO in a way which resembles the current state of deterministic dual core - read from memory on the CPU thread, but process the commands on the GPU thread. This will lead to determinism for command processor behavior (e.g. FIFO breakpoints, hi/low watermark interrupts), except EFB copies to RAM, and BP token interrupts.
However, this is a much more significant task, with far larger chances of regressions, so I pulled this change out to fix RS3, in the meantime, at least. And perhaps new motivation to make full MMU faster ;).
This gets Rogue Squadron III in-game again on Single Core only.
F-Zero GX no longer throws Unknown Opcodes all the time at boot on Single Core.
Gladius now reaches in-game (SyncGPU Dualcore only) but seems to randomly crash.
Planet 51 and Datel Discs (confirmed fixed in the bigger change mentioned in the text) remain broken with this subset of changes.
I honestly doubt that those 1000 cycles trigger a GPU reset. IIRC those GPU resets aren't because of executing the GPU only every 1000 cycles, they appeared because we've started to only execute the GPU if we have more ticks available. I think we need much faster feedback (in terms of eg interrupts), but we don't need it to execute the command buffer that fast.