Fix (unreported): prefetching wastes resources when end frame is reached

This bug is not really visible for user. When end frame is reached by
prefetching thread, it doesn't stop and keeps on getting images from
cache.

Add chech for this situation and simplify logic involved in suspending,
so it's easier to read.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D7757
This commit is contained in:
Richard Antalik 2020-05-22 13:31:49 +02:00
parent c4edc6f3f7
commit 4066c921fb
Notes: blender-bot 2023-02-13 11:55:59 +01:00
Referenced by commit 0d0df683d9, Fix(unreported): Crash on prefetching while transforming strip.
1 changed files with 35 additions and 21 deletions

View File

@ -179,12 +179,17 @@ static bool seq_prefetch_is_cache_full(Scene *scene)
return BKE_sequencer_cache_recycle_item(pfjob->scene) == false;
}
static float seq_prefetch_cfra(PrefetchJob *pfjob)
{
return pfjob->cfra + pfjob->num_frames_prefetched;
}
void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end)
{
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
*start = pfjob->cfra;
*end = pfjob->cfra + pfjob->num_frames_prefetched;
*end = seq_prefetch_cfra(pfjob);
}
static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
@ -198,8 +203,7 @@ static void seq_prefetch_free_depsgraph(PrefetchJob *pfjob)
static void seq_prefetch_update_depsgraph(PrefetchJob *pfjob)
{
DEG_evaluate_on_framechange(
pfjob->bmain_eval, pfjob->depsgraph, pfjob->cfra + pfjob->num_frames_prefetched);
DEG_evaluate_on_framechange(pfjob->bmain_eval, pfjob->depsgraph, seq_prefetch_cfra(pfjob));
}
static void seq_prefetch_init_depsgraph(PrefetchJob *pfjob)
@ -347,7 +351,7 @@ static bool seq_prefetch_do_skip_frame(Scene *scene)
{
Editing *ed = scene->ed;
PrefetchJob *pfjob = seq_prefetch_job_get(scene);
float cfra = pfjob->cfra + pfjob->num_frames_prefetched;
float cfra = seq_prefetch_cfra(pfjob);
Sequence *seq_arr[MAXSEQ + 1];
int count = BKE_sequencer_get_shown_sequences(ed->seqbasep, cfra, 0, seq_arr);
SeqRenderData *ctx = &pfjob->context_cpy;
@ -403,11 +407,30 @@ static bool seq_prefetch_do_skip_frame(Scene *scene)
return false;
}
static bool seq_prefetch_need_suspend(PrefetchJob *pfjob)
{
return seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain) ||
(seq_prefetch_cfra(pfjob) >= pfjob->scene->r.efra);
}
static void seq_prefetch_do_suspend(PrefetchJob *pfjob)
{
BLI_mutex_lock(&pfjob->prefetch_suspend_mutex);
while (seq_prefetch_need_suspend(pfjob) &&
(pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE) && !pfjob->stop) {
pfjob->waiting = true;
BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex);
seq_prefetch_update_area(pfjob);
}
pfjob->waiting = false;
BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex);
}
static void *seq_prefetch_frames(void *job)
{
PrefetchJob *pfjob = (PrefetchJob *)job;
while (pfjob->cfra + pfjob->num_frames_prefetched <= pfjob->scene->r.efra) {
while (seq_prefetch_cfra(pfjob) <= pfjob->scene->r.efra) {
pfjob->scene_eval->ed->prefetch_job = NULL;
seq_prefetch_update_depsgraph(pfjob);
@ -415,7 +438,7 @@ static void *seq_prefetch_frames(void *job)
BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene,
&pfjob->context_cpy.scene->id,
adt,
pfjob->cfra + pfjob->num_frames_prefetched,
seq_prefetch_cfra(pfjob),
ADT_RECALC_ALL,
false);
@ -432,26 +455,17 @@ static void *seq_prefetch_frames(void *job)
continue;
}
ImBuf *ibuf = BKE_sequencer_give_ibuf(
&pfjob->context_cpy, pfjob->cfra + pfjob->num_frames_prefetched, 0);
ImBuf *ibuf = BKE_sequencer_give_ibuf(&pfjob->context_cpy, seq_prefetch_cfra(pfjob), 0);
BKE_sequencer_cache_free_temp_cache(
pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob));
IMB_freeImBuf(ibuf);
/* suspend thread */
BLI_mutex_lock(&pfjob->prefetch_suspend_mutex);
while ((seq_prefetch_is_cache_full(pfjob->scene) || seq_prefetch_is_scrubbing(pfjob->bmain)) &&
pfjob->scene->ed->cache_flag & SEQ_CACHE_PREFETCH_ENABLE && !pfjob->stop) {
pfjob->waiting = true;
BLI_condition_wait(&pfjob->prefetch_suspend_cond, &pfjob->prefetch_suspend_mutex);
seq_prefetch_update_area(pfjob);
}
pfjob->waiting = false;
BLI_mutex_unlock(&pfjob->prefetch_suspend_mutex);
/* Suspend thread if there is nothing to be prefetched. */
seq_prefetch_do_suspend(pfjob);
/* Avoid "collision" with main thread, but make sure to fetch at least few frames */
if (pfjob->num_frames_prefetched > 5 &&
(pfjob->cfra + pfjob->num_frames_prefetched - pfjob->scene->r.cfra) < 2) {
(seq_prefetch_cfra(pfjob) - pfjob->scene->r.cfra) < 2) {
break;
}
@ -464,7 +478,7 @@ static void *seq_prefetch_frames(void *job)
}
BKE_sequencer_cache_free_temp_cache(
pfjob->scene, pfjob->context.task_id, pfjob->cfra + pfjob->num_frames_prefetched);
pfjob->scene, pfjob->context.task_id, seq_prefetch_cfra(pfjob));
pfjob->running = false;
pfjob->scene_eval->ed->prefetch_job = NULL;