Skip to content
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

core: Add timeline_debug feature that logs all gotos and asserts if they desync #7334

Merged
merged 5 commits into from
Aug 20, 2022

Conversation

kmeisthax
Copy link
Member

Ruffle keeps track of all movie clips' timelines via a struct member called tag_stream_pos. This is updated whenever a clip runs a frame, loops back to the start, or is given a goto command from script code, and should always point to the end of the current frame's tags (with some exceptions). If this invariant is broken, the tag stream is said to have desynchronized. The timeline no longer works correctly in the presence of fast-forwarding operations until a rewind occurs. The current implementation of AVM2 timeline operations suffers from a number of goto-related bugs that trigger desyncs.

This PR adds a new feature called timeline_debug, analogous to the avm_debug feature that prints out every stack operation. When enabled, timeline_debug will print out every goto, as well as assert that the goto started and ended in the correct spot. We also run the entire test suite with this feature enabled so that those tests will assert if they desync.

As I mentioned above, there are exceptions to the invariants on tag_stream_pos. Specifically:

  • Gotos to frames that do not exist or have not loaded do not run the target frame (since it was never reached), and thus desync deliberately.
  • AVM2 introduces the concept of frame phases, in which the same tags are run in multiple passes. In certain phases the frame number is expected to update while we are still processing tags for the prior frame, and we cannot keep the two in sync.

For the time being, the first desync on the list is being explicitly checked for and corrected. My assumption is that, at least for a non-progressive-loading player like ours, there is no way to actually trigger a fast-forwarding goto off the back of one that didn't hit its target frame. It may make sense to correct for it without timeline_debug but that's probably outside the scope of this PR.

The second desync is a huge part of why the frame events fixes PR has been such a long-running project. I have made no attempt to account for it in this PR; as doing so requires the frame phase tracking logic from #7048. The existing suite of AVM2 tests work with the asserts enabled.

…m positions against the list of stream boundaries.
…ing the target frame.

If we try to go to a frame that doesn't exist, or hasn't been loaded yet, we will stop on the last available frame, but skip any tags that would have run there. This is technically a desync, but it hasn't caused any problems so far as any further timeline interaction would trigger a rewind (which isn't affected by desyncs).

Of course, now that we're actually testing the tag stream position it *does* cause problems. We actually have to fix up the position to be correct even though it will never be used (hopefully). It may be prudent to do this outside of the `timeline_debug` feature as well in the future.
@Herschel
Copy link
Member

Thank you!

@Herschel Herschel merged commit f66e54b into ruffle-rs:master Aug 20, 2022
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.

None yet

2 participants