Changeset View
Changeset View
Standalone View
Standalone View
source/blender/sequencer/intern/prefetch.c
| Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_build.h" | #include "DEG_depsgraph_build.h" | ||||
| #include "DEG_depsgraph_debug.h" | #include "DEG_depsgraph_debug.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "SEQ_iterator.h" | |||||
| #include "SEQ_prefetch.h" | #include "SEQ_prefetch.h" | ||||
| #include "SEQ_render.h" | #include "SEQ_render.h" | ||||
| #include "SEQ_sequencer.h" | #include "SEQ_sequencer.h" | ||||
| #include "image_cache.h" | #include "image_cache.h" | ||||
| #include "prefetch.h" | #include "prefetch.h" | ||||
| #include "render.h" | #include "render.h" | ||||
| ▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | void seq_prefetch_free(Scene *scene) | ||||
| BLI_mutex_end(&pfjob->prefetch_suspend_mutex); | BLI_mutex_end(&pfjob->prefetch_suspend_mutex); | ||||
| BLI_condition_end(&pfjob->prefetch_suspend_cond); | BLI_condition_end(&pfjob->prefetch_suspend_cond); | ||||
| seq_prefetch_free_depsgraph(pfjob); | seq_prefetch_free_depsgraph(pfjob); | ||||
| BKE_main_free(pfjob->bmain_eval); | BKE_main_free(pfjob->bmain_eval); | ||||
| MEM_freeN(pfjob); | MEM_freeN(pfjob); | ||||
| scene->ed->prefetch_job = NULL; | scene->ed->prefetch_job = NULL; | ||||
| } | } | ||||
| /* Skip frame if we need to render 3D scene strip. Rendering 3D scene requires main lock or setting | /* Query all effect strips that are directly or indirectly connected to seq_reference. */ | ||||
| * up render job that doesn't have API to do openGL renders which can be used for sequencer. */ | static void query_strip_effect_chain(Sequence *seq_reference, | ||||
| static bool seq_prefetch_do_skip_frame(PrefetchJob *pfjob, ListBase *seqbase) | ListBase *seqbase, | ||||
| SeqCollection *collection) | |||||
| { | { | ||||
| float cfra = seq_prefetch_cfra(pfjob); | if (!SEQ_collection_append_strip(seq_reference, collection)) { | ||||
| Sequence *seq_arr[MAXSEQ + 1]; | return; /* Strip is already in set, so all effects connected to it are as well. */ | ||||
| int count = seq_get_shown_sequences(seqbase, cfra, 0, seq_arr); | } | ||||
| SeqRenderData *ctx = &pfjob->context_cpy; | |||||
| ImBuf *ibuf = NULL; | |||||
| /* Disable prefetching 3D scene strips, but check for disk cache. */ | /* Find all strips that seq_reference is connected to. */ | ||||
| for (int i = 0; i < count; i++) { | if (seq_reference->type & SEQ_TYPE_EFFECT) { | ||||
| if (seq_arr[i]->type == SEQ_TYPE_META && | if (seq_reference->seq1) { | ||||
| seq_prefetch_do_skip_frame(pfjob, &seq_arr[i]->seqbase)) { | query_strip_effect_chain(seq_reference->seq1, seqbase, collection); | ||||
| return true; | } | ||||
| if (seq_reference->seq2) { | |||||
| query_strip_effect_chain(seq_reference->seq2, seqbase, collection); | |||||
| } | |||||
| if (seq_reference->seq3) { | |||||
| query_strip_effect_chain(seq_reference->seq3, seqbase, collection); | |||||
| } | |||||
| } | |||||
| /* Find all strips connected to seq_reference. */ | |||||
| LISTBASE_FOREACH (Sequence *, seq_test, seqbase) { | |||||
| if (seq_test->seq1 == seq_reference || seq_test->seq2 == seq_reference || | |||||
| seq_test->seq3 == seq_reference) { | |||||
| query_strip_effect_chain(seq_test, seqbase, collection); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (seq_arr[i]->type == SEQ_TYPE_SCENE && (seq_arr[i]->flag & SEQ_SCENE_STRIPS) == 0) { | bool seq_prefetch_must_skip_frame(PrefetchJob *pfjob, Sequence *seq, bool is_last_strip) | ||||
| { | |||||
| ImBuf *ibuf = NULL; | |||||
| SeqRenderData *ctx = &pfjob->context_cpy; | |||||
| float cfra = seq_prefetch_cfra(pfjob); | |||||
| if (seq->type == SEQ_TYPE_SCENE && (seq->flag & SEQ_SCENE_STRIPS) == 0) { | |||||
| int cached_types = 0; | int cached_types = 0; | ||||
| ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT); | ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_FINAL_OUT); | ||||
| if (ibuf != NULL) { | if (ibuf != NULL) { | ||||
| cached_types |= SEQ_CACHE_STORE_FINAL_OUT; | cached_types |= SEQ_CACHE_STORE_FINAL_OUT; | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| ibuf = NULL; | ibuf = NULL; | ||||
| } | } | ||||
| ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_COMPOSITE); | ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_COMPOSITE); | ||||
| if (ibuf != NULL) { | if (ibuf != NULL) { | ||||
| cached_types |= SEQ_CACHE_STORE_COMPOSITE; | cached_types |= SEQ_CACHE_STORE_COMPOSITE; | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| ibuf = NULL; | ibuf = NULL; | ||||
| } | } | ||||
| ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED); | ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_PREPROCESSED); | ||||
| if (ibuf != NULL) { | if (ibuf != NULL) { | ||||
| cached_types |= SEQ_CACHE_STORE_PREPROCESSED; | cached_types |= SEQ_CACHE_STORE_PREPROCESSED; | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| ibuf = NULL; | ibuf = NULL; | ||||
| } | } | ||||
| ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW); | ibuf = seq_cache_get(ctx, seq, cfra, SEQ_CACHE_STORE_RAW); | ||||
| if (ibuf != NULL) { | if (ibuf != NULL) { | ||||
| cached_types |= SEQ_CACHE_STORE_RAW; | cached_types |= SEQ_CACHE_STORE_RAW; | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| ibuf = NULL; | ibuf = NULL; | ||||
| } | } | ||||
| if ((cached_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED)) != 0) { | if ((cached_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED)) != 0) { | ||||
| continue; | return false; | ||||
| } | } | ||||
| /* It is only safe to use these cache types if strip is last in stack. */ | /* It is only safe to use these cache types if strip is last in stack. */ | ||||
| if (i == count - 1 && (cached_types & SEQ_CACHE_STORE_FINAL_OUT) != 0) { | if (is_last_strip && (cached_types & SEQ_CACHE_STORE_FINAL_OUT) != 0) { | ||||
| continue; | return false; | ||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | } | ||||
| /* Skip frame if we need to render 3D scene strip. Rendering 3D scene requires main lock or setting | |||||
| * up render job that doesn't have API to do openGL renders which can be used for sequencer. */ | |||||
| static bool seq_prefetch_do_skip_frame(PrefetchJob *pfjob, ListBase *seqbase) | |||||
| { | |||||
| float cfra = seq_prefetch_cfra(pfjob); | |||||
| Sequence *seq_arr[MAXSEQ + 1]; | |||||
| int count = seq_get_shown_sequences(seqbase, cfra, 0, seq_arr); | |||||
| /* Disable prefetching 3D scene strips, but check for disk cache. */ | |||||
| for (int i = 0; i < count; i++) { | |||||
| if (seq_arr[i]->type == SEQ_TYPE_META && | |||||
| seq_prefetch_do_skip_frame(pfjob, &seq_arr[i]->seqbase)) { | |||||
| return true; | return true; | ||||
| } | } | ||||
| if (seq_prefetch_must_skip_frame(pfjob, seq_arr[i], i == count - 1)) { | |||||
| return true; | |||||
| } | |||||
| /* seq_get_shown_sequences hides effect sources, so scene strips must be looked up through | |||||
| * effect chain. */ | |||||
| if ((seq_arr[i]->type & SEQ_TYPE_EFFECT) != 0) { | |||||
| SeqCollection *collection = SEQ_query_by_reference( | |||||
| seq_arr[i], seqbase, query_strip_effect_chain); | |||||
| Sequence *chain_seq; | |||||
| SEQ_ITERATOR_FOREACH (chain_seq, collection) { | |||||
| if (seq_prefetch_must_skip_frame(pfjob, chain_seq, false)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool seq_prefetch_need_suspend(PrefetchJob *pfjob) | static bool seq_prefetch_need_suspend(PrefetchJob *pfjob) | ||||
| { | { | ||||
| return seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain) || | return seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain) || | ||||
| Show All 35 Lines | while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) { | ||||
| pfjob->scene_eval->ed->prefetch_job = pfjob; | pfjob->scene_eval->ed->prefetch_job = pfjob; | ||||
| ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(pfjob->scene, false)); | ListBase *seqbase = SEQ_active_seqbase_get(SEQ_editing_get(pfjob->scene, false)); | ||||
| if (seq_prefetch_do_skip_frame(pfjob, seqbase)) { | if (seq_prefetch_do_skip_frame(pfjob, seqbase)) { | ||||
| pfjob->num_frames_prefetched++; | pfjob->num_frames_prefetched++; | ||||
| continue; | continue; | ||||
| } | } | ||||
| BKE_main_lock(pfjob->bmain); | |||||
| ImBuf *ibuf = SEQ_render_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0); | ImBuf *ibuf = SEQ_render_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0); | ||||
| BKE_main_unlock(pfjob->bmain); | |||||
| seq_cache_free_temp_cache(pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); | seq_cache_free_temp_cache(pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob)); | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| /* Suspend thread if there is nothing to be prefetched. */ | /* Suspend thread if there is nothing to be prefetched. */ | ||||
| seq_prefetch_do_suspend(pfjob); | seq_prefetch_do_suspend(pfjob); | ||||
| /* Avoid "collision" with main thread, but make sure to fetch at least few frames */ | /* Avoid "collision" with main thread, but make sure to fetch at least few frames */ | ||||
| if (pfjob->num_frames_prefetched > 5 && | if (pfjob->num_frames_prefetched > 5 && | ||||
| ▲ Show 20 Lines • Show All 98 Lines • Show Last 20 Lines | |||||