Files
test2/source/blender/sequencer/SEQ_thumbnail_cache.hh
Aras Pranckevicius 4c8f22447f VSE: Faster timeline thumbnail drawing
VSE timeline, when many (hundreds/thousands) of thumbnails were visible, was
very slow to redraw. This PR makes them 3-10x faster to redraw, by stopping
doing things that are slow :) Part of #126087 thumbnail improvements task.

- No longer do mute semitransparency or corner rounding on the CPU, do it in
  shader instead.
- Stop creating a separate GPU texture for each thumbnail, on every repaint,
  and drawing each thumbnail as a separate draw call. Instead, put thumbnails
  into a single texture atlas (using a simple shelf packing algorithm), and
  draw them in batch, passing data via UBO. The atlas is still re-created every
  frame, but that does not seem to be a performance issue. Thumbnails are
  cropped horizontally based on how much of their parts are visible (e.g. a
  narrow strip on screen), so realistically the atlas size is kinda
  proportional to screen size, and ends up being just several megabytes of data
  transfer between CPU -> GPU each frame.

On this Sprite Fright edit timeline view (612 visible thumbnails), time taken
to repaint the timeline window:

- Mac (M1 Max, Metal): 68.1ms -> 4.7ms
- Windows (Ryzen 5950X, RTX 3080Ti, OpenGL): 23.7ms -> 6.8ms

This also fixes a visual issue with thumbnails, where when strips are very
tall, the "rounded corners" that were poked right into the thumbnail bitmap
on the CPU were showing up due to actual bitmap being scaled up a lot.

Pull Request: https://projects.blender.org/blender/blender/pulls/126972
2024-09-03 08:25:15 +02:00

61 lines
1.7 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup sequencer
*/
#pragma once
struct bContext;
struct ImBuf;
struct rctf;
struct Sequence;
struct Scene;
#include "BLI_function_ref.hh"
#include <string>
namespace blender::seq {
static constexpr int SEQ_THUMB_SIZE = 256;
/**
* Get a thumbnail image for given strip `seq` at `timeline_frame`.
*
* The function can return null if a strip type does not have a thumbnail, a source media file is
* not found, or the thumbnail has not been loaded yet.
*
* A "closest" thumbnail if there is no exact match can also be returned, e.g. for a movie strip
* the closest frame that has a thumbnail already.
*
* When there is no exact match, a request to load a thumbnail will be internally added and
* processed in the background. */
ImBuf *thumbnail_cache_get(const bContext *C,
Scene *scene,
const Sequence *seq,
float timeline_frame);
/**
* If total amount of resident thumbnails is too large, try to remove oldest-used ones to
* keep the cache size in check.
*/
void thumbnail_cache_maintain_capacity(Scene *scene);
void thumbnail_cache_invalidate_strip(Scene *scene, const Sequence *seq);
/**
* Discard in-flight thumbnail loading requests that are outside of the given view (X coordinate:
* timeline frames, Y coordinate: channels).
*/
void thumbnail_cache_discard_requests_outside(Scene *scene, const rctf &rect);
void thumbnail_cache_clear(Scene *scene);
void thumbnail_cache_destroy(Scene *scene);
bool strip_can_have_thumbnail(const Scene *scene, const Sequence *seq);
} // namespace blender::seq