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

Fix: flickery frames due to leaky event handling #36

Merged
merged 2 commits into from
Nov 12, 2024

Conversation

froyo-np
Copy link
Collaborator

@froyo-np froyo-np commented Nov 11, 2024

What:

Skyler's integration prototype revealed some suspicious flickering when zooming around. This lead me to find a new instance of a bug I previously created and fixed in the BKP's RenderManager, in which the delivery of events to the system that manages frames was very confusing.

TLDR - a frame can finish before its even returned to the function trying to start it - this is nice for perf, but very confusing. This is still true, but the lifecycle events will be delivered in a more consistant order, and the helpful render-server now handles this situation better. Previously, it would start many frames all at once, because each frame was assumed to be the first.

…in a confusing way, due to the asynchronous nature of the events vs. the desire to synchronously render whenever possible, it was common for frames to finish before even being returned from the begin() function, leading to confusing behavior.
@@ -168,12 +168,19 @@ export class RenderServer {
}
};
this.clients.set(client, {
frame: renderFn(image, this.cache, hijack),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was the bulk of the issue experienced by Skyler's work - renderFn() often returns a frame that is already finished - that means that event handlers (like the one that copies the webGL buffer to the screen) run before we even write this little object to our map of clients for the render server - this of course would be surprising for everyone!

// this is a good thing for performance, but potentially confusing - so we do our book-keeping before we actually start rendering:
const aboutToStart = this.clients.get(client); // this is the record we just put into the clients map - TS just wants to be sure it really exists:
if (aboutToStart) {
aboutToStart.frame = renderFn(image, this.cache, hijack)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fix is to start the frame AFTER writing down important things like its private image buffer, size, etc.

reportStatus({ status: 'cancelled' });
},
};
doWorkOnQueue(interval, false)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is where we do rendering work as fast as we can - by not waiting for our setInterval() function to do it for us. To help prevent confusing situations, I now pass false to the worker, indicating that all its lifecycle callbacks should happen later, on a promise

@@ -225,6 +225,7 @@ export class AsyncDataCache<SemanticKey extends RecordKey, CacheKey extends Reco
workingSet: Record<SemanticKey, () => Promise<D>>,
use: (items: Record<SemanticKey, D>) => void,
toCacheKey: (semanticKey: SemanticKey) => CacheKey,
// TODO: consider removing taskFinished - it would be more simple to let the caller handle this in their use() function
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to do later!

@froyo-np
Copy link
Collaborator Author

We can revisit this whole idea someday - but for now I think this is an ok way to go - its particularly nice because it should require no code changes for users of this package.

@froyo-np froyo-np marked this pull request as ready for review November 11, 2024 23:31
Copy link
Contributor

@TheMooseman TheMooseman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

examples are all working for me!

Copy link
Collaborator

@lanesawyer lanesawyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code makes sense, performance is better on this one than main! I do see the SVG still jump a little sometimes when loading new chunks 🤔

@froyo-np froyo-np merged commit 0e3f675 into main Nov 12, 2024
4 of 5 checks passed
@froyo-np froyo-np deleted the noah/fix-frame-lifecycle-reporting branch November 12, 2024 19:07
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.

3 participants