Page MenuHome

Fix T70612: Sequencer Crash on enabling Prefetch
ClosedPublic

Authored by Richard Antalik (ISS) on Apr 24 2020, 6:15 PM.

Details

Summary

It is not possible to run render job from within scene provided by DEG_get_evaluated_scene()
Use BKE_scene_copy() instead to create runtime scene for prefetching.

Also pointer to windowmanager has to be provided to bmain runtime copy. windowmanager is needed by at least by BKE_image_editors_update_frame() via BKE_scene_graph_update_for_newframe()

Diff Detail

Repository
rB Blender

Event Timeline

Richard Antalik (ISS) requested review of this revision.Apr 24 2020, 6:15 PM
Richard Antalik (ISS) created this revision.
Brecht Van Lommel (brecht) requested changes to this revision.Apr 24 2020, 10:37 PM

BKE_scene_copy can't be used like this. It will increase user counts on any datablocks it references, which should not happen for such temporary data structures for evaluation. A full scene copy can also be quite memory intensive.

Can you explain why it's not possible to run a render job from within a scene provided by DEG_get_evaluated_scene()? Since prefetching is already a job itself, could it just render without the jobs system in that case?

This revision now requires changes to proceed.Apr 24 2020, 10:37 PM

BKE_scene_copy can't be used like this. It will increase user counts on any datablocks it references, which should not happen for such temporary data structures for evaluation.

I think I could copy data without increasing usercount without causing problems. But I would have to check to be sure.

A full scene copy can also be quite memory intensive.

Scene with sequencer should not really contain too much data, but yes, it can. To copy as little data as possible here I would have to go through all dependencies and copy only what's needed. I don't know if this is really possible now.

Can you explain why it's not possible to run a render job from within a scene provided by DEG_get_evaluated_scene()?

I don't exactly know why, but there are multiple asserts for checking that provided scene is not COW already BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) == 0) so DEG_graph_build_for_render_pipeline() will fail.

Since prefetching is already a job itself, could it just render without the jobs system in that case?

For a quick test if that would work, I supplied pre-initialized depsgraph to RE_RenderFrame(). scene was same as scene_eval in this case. However this failed on engine_depsgraph_init()

I guess, that I can do same trick as I am doing for cache - swap context for real one to render the scene. This shouldn't cause problems, because sequencer is locked while prefetch is running.

Richard Antalik (ISS) updated this revision to Diff 24060.EditedApr 25 2020, 2:44 AM

Swapping context works, in sense that it is not crashing, but animation is not evaluated properly in sequencer scene.

However I now question if I do even need runtime scene copy. I can't remember it's purpose clearly.

Edit: Obviously I need to drive scene copy cfra and update animation... I should go to sleep.

I have looked into this a bit further and another issue with using original scene for prefetching is that it's animdata are updated for different frame which can be seen in panels while UI is drawing. Also tweaking properties of strips will affect running prefetch job.
Therefore I must use copy of scene for prefetching.

Alternatively I could use approach in D6117 but at least try to look for cached images in disk cache.

I tried to find the right solution here, but my advice would be for 2.83 to disable prefetching in .blend files with scene strips. Because this is going to need some bigger refactoring to get reliable results.

The first problem is the behavior. Depending on BLI_thread_is_main() it will use either an OpenGL preview render or final render. That means that prefetching will use final render, while scrubbing will use a preview render. That gives a mix of different frames, which is not useful. So this should be fixed, but that in turn implies that OpenGL preview render needs to be made to work in the prefetch thread.

Both the OpenGL preview render and final render currently can't run correctly from the prefetch thread.

For the final render, using the original scene as this patch does is a solution. But it requires some refactoring so the original scene is not actually modified, only the copy of it that is created inside RE_RenderFrame. I did work towards that in P1372, but this seems too complex a change for 2.83.

For OpenGL preview render, I see two solutions.

  • Create a second dependency graph based on the original scene like final render does. But ensure it is cached for performance.
  • Use the viewport dependency graph, but ensure the main thread and prefetch thread are not accessing it at the same time.

The purpose of OpenGL preview render is fast previews. And I think probably a second dependency graph copy just for prefetching takes up too much CPU and GPU memory?

I think we should find a way to mutex lock that dependency graph so the prefetch job can access it safely, even if that blocks the UI drawing for a bit. It will be effectively blocked by OpenGL single-threaded rendering anyway so I'm not sure it's that bad. The easiest solution would be add some mutex in the Blender main loop, so all other work is stopped while the prefetch job is preview rendering such a scene (we have something like that in the jobs system, see WM_job_main_thread_lock_acquire). But maybe we can find something more fine grained.

In simple cases, the scene being used for OpenGL render is not even displayed anywhere besides the sequencer. You need to have two windows open with different scenes. But functions like DEG_id_tag_update do loop over all dependency graphs, so it can be modified from many places.

Brecht Van Lommel (brecht) requested changes to this revision.May 6 2020, 11:36 PM
This revision now requires changes to proceed.May 6 2020, 11:36 PM

I tried to find the right solution here, but my advice would be for 2.83 to disable prefetching in .blend files with scene strips. Because this is going to need some bigger refactoring to get reliable results.

This makes sense. Though I would still like to attempt to load cached images.

My reasoning is, that if VSE will use openGL to process images, we may want to use prefech primarily to read disk cache (to mitigate delay of cold reads).
It could still have mode that uses WM_job_main_thread_lock_acquire but goal is to make playback smooth. I will do some tests to see if there is potential to improve performance for lighter scenes, but personally I would rather focus on GPU processing.

Skip prefetching of scene strips, but check for disk cache

This revision is now accepted and ready to land.May 11 2020, 10:08 AM