gpu: [compute] cache and re-use drawing operations from the previous frame

The compute renderer is more expensive to run than the old renderer on
low-end GPUs, and even more so on CPUs. To ensure good performance
regardless of the end-user device, this change implements automatic
re-use of content rendered in the frame before the current.

The basic idea is that every drawing operation (PaintOp), along with its
transform and clipping, can be hashed and efficiently looked up. A naïve
caching approach is then to rasterize every operation to separate
sections of several large texture atlases, turning a cache hit into a
very cheap texture copy.

However, for scenes with lots of overlapping operations, the resulting
texture memory from separating the operations would be much larger than
the memory for just the window framebuffer.

So instead of caching individual operations, this change caches layers,
which are sequences of drawing operations. It starts by putting all
operations into a single layer. Then, if the subsequent frame re-uses a
sub-sequence of that larger layer, it is split.

For example, consider a UI similar to the kitchen sample:

Hello, Gio

<Editor>

<Line Editor>

<Button> <Button> <Button>

<ProgressBar>

<Checkbox> <Toggle>

In the first frame, all of the drawing operations comprising the UI will
be stored and cached in a single layer. In the second frame the
progress bar will have moved and the renderer splits the UI into three
layers: layer A for everything up to (but not including) the progress
bar, layer B with just the progress bar, and layer C for the rest. Note
that nothing has been re-used yet. In the third frame, the progress bar
moves again, and this time layer A and C can be copied from the cache
only the progress bar needs redrawing through the compute programs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-04-22 10:30:18 +02:00
parent 938e51f111
commit e6c31a02fd
4 changed files with 786 additions and 338 deletions
+13 -14
View File
@@ -4,19 +4,18 @@
precision highp float;
layout(binding = 0) uniform Block {
vec2 scale;
vec2 pos;
vec2 uvScale;
} _block;
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 uv;
layout(location = 0) out vec2 vUV;
void main() {
switch (gl_VertexIndex) {
case 0:
gl_Position = vec4(-1.0, +1.0, 0.0, 1.0);
break;
case 1:
gl_Position = vec4(+1.0, +1.0, 0.0, 1.0);
break;
case 2:
gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);
break;
case 3:
gl_Position = vec4(+1.0, -1.0, 0.0, 1.0);
break;
}
vUV = uv*_block.uvScale;
gl_Position = vec4(pos*_block.scale + _block.pos, 0, 1);
}