New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement run-ahead #782
Comments
Just thinking out loud: Instead of running two instances in parallel and recreating the second one via fast-forwarding when an external event comes in, the same effect is achievable by rewinding. In detail:
When the instance gets dirty due to an external event (joystick movement, etc.), fast-rewind by n frames by copying over a state from the ring buffer and fast-forward by emulating n frames. Pros:
Cons:
UPDATE: There is another big Con: We cannot easily rewind what's been written in the audio buffer. The advantage of the current approach is that the run-ahead instance only provides the texture. Audio is still coming from the main instance. |
Update: The run-ahead instance is only recreated when needed. In addition, frames that are not displayed are computed in headless mode, which further saves computation time. Now, run-ahead can be used in debug builds without any issues. The new run-ahead logic looks as follows and should be pretty self-explanatory: void
Emulator::computeFrame()
{
if (config.runAhead) {
// Run the main instance
main.executeHeadless();
// Recreate the run-ahead instance if necessary
if (main.isDirty || RUA_ON_STEROIDS) recreateRunAheadInstance();
// Run the runahead instance
ahead.execute();
} else {
// Run the main instance
main.execute();
}
}
void
Emulator::recreateRunAheadInstance()
{
// Recreate the runahead instance from scratch
ahead = main; main.isDirty = false;
if (RUA_DEBUG && ahead != main) {
main.dump(Category::Checksums);
ahead.dump(Category::Checksums);
fatal("Corrupted run-ahead clone detected");
}
// Advance to the proper frame
ahead.fastForward(config.runAhead - 1);
}
void
C64::fastForward(isize frames)
{
auto target = frame + frames;
// Execute until the target frame has been reached
while (frame < target) executeHeadless();
} |
There is a neat summary of the run-ahead technique here: https://bsnes.org/articles/input-run-ahead
I think the run-ahead technique can be integrated into VirtualC64 with reasonable effort, and the emulator would benefit significantly from it.
As preparatory work, the following should be done:
C64
class inherit fromThread
anymore. Instead, create a newEmulator
class which inherits fromThread
and contains aC64
object as a member. Later, this class will maintain a second run-ahead instance.clone
function that copies the contents of one emulator instance to another.The text was updated successfully, but these errors were encountered: