gpu: Be more aggressive about GC'ing dead textures
When we encounter many dead textures, we want to GC. Textures can take up fds (potentially even more than 1) and when we are not collecting them quickly enough, we may run out of fds. So GC when more then 50 dead textures exist. An example for this happening is recent Mesa with llvmpipe udmabuf support, which takes 2 fds per texture and the test in testsuite/gdk/memorytexture that creates 800 textures of ~1 pixel each, which it diligently releases but doesn't GC. Related: #6917
This commit is contained in:
@@ -48,6 +48,7 @@ struct _GskGpuCache
|
|||||||
|
|
||||||
GskGpuCachedAtlas *current_atlas;
|
GskGpuCachedAtlas *current_atlas;
|
||||||
|
|
||||||
|
/* atomic */ gsize dead_textures;
|
||||||
/* atomic */ gsize dead_texture_pixels;
|
/* atomic */ gsize dead_texture_pixels;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -372,6 +373,7 @@ struct _GskGpuCachedTexture
|
|||||||
* weak ref.
|
* weak ref.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
gsize *dead_textures_counter;
|
||||||
gsize *dead_pixels_counter;
|
gsize *dead_pixels_counter;
|
||||||
|
|
||||||
GdkTexture *texture;
|
GdkTexture *texture;
|
||||||
@@ -470,7 +472,10 @@ gsk_gpu_cached_texture_destroy_cb (gpointer data)
|
|||||||
GskGpuCachedTexture *self = data;
|
GskGpuCachedTexture *self = data;
|
||||||
|
|
||||||
if (!gsk_gpu_cached_texture_is_invalid (self))
|
if (!gsk_gpu_cached_texture_is_invalid (self))
|
||||||
g_atomic_pointer_add (self->dead_pixels_counter, ((GskGpuCached *) self)->pixels);
|
{
|
||||||
|
g_atomic_pointer_add (self->dead_textures_counter, 1);
|
||||||
|
g_atomic_pointer_add (self->dead_pixels_counter, ((GskGpuCached *) self)->pixels);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_atomic_int_dec_and_test (&self->use_count))
|
if (g_atomic_int_dec_and_test (&self->use_count))
|
||||||
g_free (self);
|
g_free (self);
|
||||||
@@ -508,6 +513,7 @@ gsk_gpu_cached_texture_new (GskGpuCache *cache,
|
|||||||
self->image = g_object_ref (image);
|
self->image = g_object_ref (image);
|
||||||
self->color_state = color_state;
|
self->color_state = color_state;
|
||||||
((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image);
|
((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image);
|
||||||
|
self->dead_textures_counter = &cache->dead_textures;
|
||||||
self->dead_pixels_counter = &cache->dead_texture_pixels;
|
self->dead_pixels_counter = &cache->dead_texture_pixels;
|
||||||
self->use_count = 2;
|
self->use_count = 2;
|
||||||
|
|
||||||
@@ -537,6 +543,7 @@ struct _GskGpuCachedTile
|
|||||||
* list) and by the texture (via weak ref)
|
* list) and by the texture (via weak ref)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
gsize *dead_textures_counter;
|
||||||
gsize *dead_pixels_counter;
|
gsize *dead_pixels_counter;
|
||||||
|
|
||||||
GskGpuImage *image;
|
GskGpuImage *image;
|
||||||
@@ -609,7 +616,10 @@ gsk_gpu_cached_tile_destroy_cb (gpointer data)
|
|||||||
GskGpuCachedTile *self = data;
|
GskGpuCachedTile *self = data;
|
||||||
|
|
||||||
if (!gsk_gpu_cached_tile_is_invalid (self))
|
if (!gsk_gpu_cached_tile_is_invalid (self))
|
||||||
g_atomic_pointer_add (self->dead_pixels_counter, ((GskGpuCached *) self)->pixels);
|
{
|
||||||
|
g_atomic_pointer_add (self->dead_textures_counter, 1);
|
||||||
|
g_atomic_pointer_add (self->dead_pixels_counter, ((GskGpuCached *) self)->pixels);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_atomic_int_dec_and_test (&self->use_count))
|
if (g_atomic_int_dec_and_test (&self->use_count))
|
||||||
g_free (self);
|
g_free (self);
|
||||||
@@ -649,6 +659,7 @@ gsk_gpu_cached_tile_new (GskGpuCache *cache,
|
|||||||
self->image = g_object_ref (image);
|
self->image = g_object_ref (image);
|
||||||
self->color_state = gdk_color_state_ref (color_state);
|
self->color_state = gdk_color_state_ref (color_state);
|
||||||
((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image);
|
((GskGpuCached *)self)->pixels = gsk_gpu_image_get_width (image) * gsk_gpu_image_get_height (image);
|
||||||
|
self->dead_textures_counter = &cache->dead_textures;
|
||||||
self->dead_pixels_counter = &cache->dead_texture_pixels;
|
self->dead_pixels_counter = &cache->dead_texture_pixels;
|
||||||
self->use_count = 2;
|
self->use_count = 2;
|
||||||
|
|
||||||
@@ -894,6 +905,7 @@ gsk_gpu_cache_gc (GskGpuCache *self,
|
|||||||
is_empty &= cached->stale;
|
is_empty &= cached->stale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_atomic_pointer_set (&self->dead_textures, 0);
|
||||||
g_atomic_pointer_set (&self->dead_texture_pixels, 0);
|
g_atomic_pointer_set (&self->dead_texture_pixels, 0);
|
||||||
|
|
||||||
if (GSK_DEBUG_CHECK (CACHE))
|
if (GSK_DEBUG_CHECK (CACHE))
|
||||||
@@ -904,6 +916,12 @@ gsk_gpu_cache_gc (GskGpuCache *self,
|
|||||||
return is_empty;
|
return is_empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_gpu_cache_get_dead_textures (GskGpuCache *self)
|
||||||
|
{
|
||||||
|
return GPOINTER_TO_SIZE (g_atomic_pointer_get (&self->dead_textures));
|
||||||
|
}
|
||||||
|
|
||||||
gsize
|
gsize
|
||||||
gsk_gpu_cache_get_dead_texture_pixels (GskGpuCache *self)
|
gsk_gpu_cache_get_dead_texture_pixels (GskGpuCache *self)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ void gsk_gpu_cache_set_time (GskGpuC
|
|||||||
gboolean gsk_gpu_cache_gc (GskGpuCache *self,
|
gboolean gsk_gpu_cache_gc (GskGpuCache *self,
|
||||||
gint64 cache_timeout,
|
gint64 cache_timeout,
|
||||||
gint64 timestamp);
|
gint64 timestamp);
|
||||||
|
gsize gsk_gpu_cache_get_dead_textures (GskGpuCache *self);
|
||||||
gsize gsk_gpu_cache_get_dead_texture_pixels (GskGpuCache *self);
|
gsize gsk_gpu_cache_get_dead_texture_pixels (GskGpuCache *self);
|
||||||
GskGpuImage * gsk_gpu_cache_get_atlas_image (GskGpuCache *self);
|
GskGpuImage * gsk_gpu_cache_get_atlas_image (GskGpuCache *self);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void
|
|||||||
gsk_gpu_device_maybe_gc (GskGpuDevice *self)
|
gsk_gpu_device_maybe_gc (GskGpuDevice *self)
|
||||||
{
|
{
|
||||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||||
gsize dead_texture_pixels;
|
gsize dead_texture_pixels, dead_textures;
|
||||||
|
|
||||||
if (priv->cache_timeout < 0)
|
if (priv->cache_timeout < 0)
|
||||||
return;
|
return;
|
||||||
@@ -88,11 +88,13 @@ gsk_gpu_device_maybe_gc (GskGpuDevice *self)
|
|||||||
if (priv->cache == NULL)
|
if (priv->cache == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
dead_textures = gsk_gpu_cache_get_dead_textures (priv->cache);
|
||||||
dead_texture_pixels = gsk_gpu_cache_get_dead_texture_pixels (priv->cache);
|
dead_texture_pixels = gsk_gpu_cache_get_dead_texture_pixels (priv->cache);
|
||||||
|
|
||||||
if (priv->cache_timeout == 0 || dead_texture_pixels > 1000000)
|
if (priv->cache_timeout == 0 || dead_textures > 50 || dead_texture_pixels > 1000 * 1000)
|
||||||
{
|
{
|
||||||
GSK_DEBUG (CACHE, "Pre-frame GC (%" G_GSIZE_FORMAT " dead pixels)", dead_texture_pixels);
|
GSK_DEBUG (CACHE, "Pre-frame GC (%" G_GSIZE_FORMAT " dead textures, %" G_GSIZE_FORMAT " dead pixels)",
|
||||||
|
dead_textures, dead_texture_pixels);
|
||||||
gsk_gpu_device_gc (self, g_get_monotonic_time ());
|
gsk_gpu_device_gc (self, g_get_monotonic_time ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user