vo_gpu_next: simplify and improve frame redrawing logic

This almost perfectly recreates the semantics of --vo=gpu, i.e.:

- still frames are never interpolated
- non-repeated frames bypass single frame cache

The only difference is that libplacebo doesn't do a cache/blit on the
full output image, but rather it re-runs the last rendering step. This
has some advantages and some drawbacks. The most notable advantage is
that it also allows re-using the image contents when the only thing that
changes is the OSD (whereas `--vo=gpu` would force a full re-render for
that). The most notable drawback is that it also implies going through
the dithering and output LUT logic on redraws. All in all, I think this
is a pretty good trade-off in favor of `--vo=gpu-next`.

Fully fixes the last remaining performance difference in #9430.
This commit is contained in:
Niklas Haas 2021-11-19 13:48:55 +01:00 committed by Niklas Haas
parent d1e9f4a159
commit 75ee35cec9
1 changed files with 6 additions and 14 deletions

View File

@ -107,6 +107,7 @@ struct priv {
struct pl_dither_params dither;
struct scaler_params scalers[SCALER_COUNT];
const struct pl_hook **hooks; // storage for `params.hooks`
const struct pl_filter_config *frame_mixer;
#ifdef PL_HAVE_LCMS
struct pl_icc_params icc;
@ -706,19 +707,6 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
break;
}
if (frame->still && mix.num_frames) {
double best = fabs(mix.timestamps[0]);
// Recreate nearest neighbour semantics on this frame mix
while (mix.num_frames > 1 && fabs(mix.timestamps[1]) < best) {
best = fabs(mix.timestamps[1]);
mix.frames++;
mix.signatures++;
mix.timestamps++;
mix.num_frames--;
}
mix.num_frames = 1;
}
// Update source crop on all existing frames. We technically own the
// `pl_frame` struct so this is kosher. This could be avoided by
// instead flushing the queue on resizes, but doing it this way avoids
@ -743,8 +731,12 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
}
}
#if PL_API_VER >= 179
p->params.skip_caching_single_frame = !frame->display_synced || frame->num_vsyncs == 1;
#endif
p->params.preserve_mixing_cache = p->inter_preserve && !frame->still;
p->params.allow_delayed_peak_detect = p->delayed_peak;
p->params.frame_mixer = frame->still ? NULL : p->frame_mixer;
// Render frame
if (!pl_render_image_mix(p->rr, &mix, &target, &p->params)) {
@ -1229,7 +1221,7 @@ static void update_render_options(struct priv *p)
// Map scaler options as best we can
p->params.upscaler = map_scaler(p, SCALER_SCALE);
p->params.downscaler = map_scaler(p, SCALER_DSCALE);
p->params.frame_mixer = opts->interpolation ? map_scaler(p, SCALER_TSCALE) : NULL;
p->frame_mixer = opts->interpolation ? map_scaler(p, SCALER_TSCALE) : NULL;
p->deband = pl_deband_default_params;
p->deband.iterations = opts->deband_opts->iterations;