1
0
Fork 0

onscreen/native: Prevent duplicate damage rectangles in copy path

Since we use the buffer age to create a union of damage rectangles from the
last n frames, we often end up with the same rectangle multiple times if an
application happens to be changing that is in the same place. This in turn
results in duplicate vertices being generated and uploaded to the GPU in
the blitting and painting paths.

Spend some time (seems to take around 15 microseconds on average on my
system) dropping duplicate rectangles using a GHashTable. This partially
pays itself back CPU-wise by having to copy fewer rectangles in
copy_shared_framebuffer_gpu, looping and calculating less in
paint_egl_image. GPU-wise it uploads less data to the GPU and makes the
shaders invoke less.

(cherry picked from commit 07e021b3a4facec18d1db64deb74b955f55321e9)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4073>
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
This commit is contained in:
Gert-dev 2024-10-10 20:36:44 +02:00 committed by Mingi Sung
parent 47293a748d
commit cfddb42d22
Signed by: sungmg
GPG key ID: 41BAFD6FFD8036C5

View file

@ -989,18 +989,41 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
if (blit_n_rectangles > 0) if (blit_n_rectangles > 0)
{ {
int i; int i;
size_t offset = 0; int offset = 0;
/* Will tend to overallocate a bit if reduction happens below, but doesn't matter much since it's pretty small. */
blit_rectangles = g_newa (MtkRectangle, blit_n_rectangles); blit_rectangles = g_newa (MtkRectangle, blit_n_rectangles);
GHashTable* hash_table = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i <= buffer_age; ++i) for (i = 0; i <= buffer_age; ++i)
{ {
memcpy (blit_rectangles + offset, int j;
secondary_gpu_state->damage_rectangles[i].rectangles,
secondary_gpu_state->damage_rectangles[i].n_rectangles * sizeof(MtkRectangle));
offset += secondary_gpu_state->damage_rectangles[i].n_rectangles; for (j = 0; j < secondary_gpu_state->damage_rectangles[i].n_rectangles; ++j)
{
char hash_table_key[100];
g_snprintf (hash_table_key,
100,
"%i_%i_%i_%i",
secondary_gpu_state->damage_rectangles[i].rectangles[j].x,
secondary_gpu_state->damage_rectangles[i].rectangles[j].y,
secondary_gpu_state->damage_rectangles[i].rectangles[j].width,
secondary_gpu_state->damage_rectangles[i].rectangles[j].height);
if (g_hash_table_lookup_extended (hash_table, hash_table_key, NULL, NULL))
continue;
g_hash_table_insert (hash_table, hash_table_key, NULL);
memcpy (&blit_rectangles[offset++], &secondary_gpu_state->damage_rectangles[i].rectangles[j], sizeof(MtkRectangle));
}
} }
g_hash_table_destroy (hash_table);
blit_n_rectangles = offset;
} }
if (!meta_renderer_native_gles3_blit_shared_bo (egl, if (!meta_renderer_native_gles3_blit_shared_bo (egl,