vulkan: Implement texture caching
And with this change, the GPU looks bored again.
This commit is contained in:
@@ -15,6 +15,14 @@
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
typedef struct _GskVulkanTextureData GskVulkanTextureData;
|
||||
|
||||
struct _GskVulkanTextureData {
|
||||
GskTexture *texture;
|
||||
GskVulkanImage *image;
|
||||
GskVulkanRenderer *renderer;
|
||||
};
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
typedef struct {
|
||||
GQuark cpu_time;
|
||||
@@ -35,6 +43,8 @@ struct _GskVulkanRenderer
|
||||
|
||||
GskVulkanRender *render;
|
||||
|
||||
GSList *textures;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
ProfileTimers profile_timers;
|
||||
#endif
|
||||
@@ -133,6 +143,16 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
|
||||
{
|
||||
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
|
||||
VkDevice device;
|
||||
GSList *l;
|
||||
|
||||
for (l = self->textures; l; l = l->next)
|
||||
{
|
||||
GskVulkanTextureData *data = l->data;
|
||||
|
||||
data->renderer = NULL;
|
||||
gsk_texture_clear_render_data (data->texture);
|
||||
}
|
||||
g_clear_pointer (&self->textures, (GDestroyNotify) g_slist_free);
|
||||
|
||||
g_clear_pointer (&self->render, gsk_vulkan_render_free);
|
||||
|
||||
@@ -237,3 +257,56 @@ gsk_vulkan_renderer_init (GskVulkanRenderer *self)
|
||||
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_renderer_clear_texture (gpointer p)
|
||||
{
|
||||
GskVulkanTextureData *data = p;
|
||||
|
||||
if (data->renderer != NULL)
|
||||
data->renderer->textures = g_slist_remove (data->renderer->textures, data);
|
||||
|
||||
g_object_unref (data->image);
|
||||
|
||||
g_slice_free (GskVulkanTextureData, data);
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
||||
GskTexture *texture,
|
||||
VkCommandBuffer command_buffer)
|
||||
{
|
||||
GskVulkanTextureData *data;
|
||||
cairo_surface_t *surface;
|
||||
GskVulkanImage *image;
|
||||
|
||||
data = gsk_texture_get_render_data (texture, self);
|
||||
if (data)
|
||||
return g_object_ref (data->image);
|
||||
|
||||
surface = gsk_texture_download (texture);
|
||||
image = gsk_vulkan_image_new_from_data (self->vulkan,
|
||||
command_buffer,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
data = g_slice_new0 (GskVulkanTextureData);
|
||||
data->image = image;
|
||||
data->texture = texture;
|
||||
data->renderer = self;
|
||||
|
||||
if (gsk_texture_set_render_data (texture, self, data, gsk_vulkan_renderer_clear_texture))
|
||||
{
|
||||
g_object_ref (data->image);
|
||||
self->textures = g_slist_prepend (self->textures, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_slice_free (GskVulkanTextureData, data);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <gsk/gskrenderer.h>
|
||||
|
||||
#include "gsk/gskvulkanimageprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_RENDERER (gsk_vulkan_renderer_get_type ())
|
||||
@@ -19,6 +21,10 @@ typedef struct _GskVulkanRendererClass GskVulkanRendererClass;
|
||||
|
||||
GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
||||
GskTexture *texture,
|
||||
VkCommandBuffer command_buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "gskvulkanimageprivate.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gskrenderer.h"
|
||||
#include "gsktextureprivate.h"
|
||||
#include "gskvulkanrendererprivate.h"
|
||||
|
||||
typedef struct _GskVulkanRenderOp GskVulkanRenderOp;
|
||||
|
||||
@@ -170,15 +170,10 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
||||
|
||||
case GSK_VULKAN_OP_TEXTURE:
|
||||
{
|
||||
cairo_surface_t *surface = gsk_texture_download (gsk_render_node_get_texture (op->node));
|
||||
op->source = gsk_vulkan_image_new_from_data (self->vulkan,
|
||||
command_buffer,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
op->source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||
gsk_render_node_get_texture (op->node),
|
||||
command_buffer);
|
||||
gsk_vulkan_render_add_cleanup_image (render, op->source);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user