Mesa (master): zink: implement a surface cache
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Mar 15 14:09:55 UTC 2021
Module: Mesa
Branch: master
Commit: 38f7faa8a49f4d8b70d7a477a2bc3255b0995e64
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=38f7faa8a49f4d8b70d7a477a2bc3255b0995e64
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Tue Feb 9 15:40:38 2021 -0500
zink: implement a surface cache
this is a global cache for all surface objects, enabling some memory
optimizations as well as improved reuse of cached descriptors
loosely based on patches from Antonio Caggiano
Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9541>
---
src/gallium/drivers/zink/zink_screen.c | 18 +++++
src/gallium/drivers/zink/zink_screen.h | 3 +
src/gallium/drivers/zink/zink_surface.c | 116 +++++++++++++++++++++++++-------
src/gallium/drivers/zink/zink_surface.h | 14 ++++
4 files changed, 125 insertions(+), 26 deletions(-)
diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c
index 504f7a72c0c..a86da07f68f 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -83,6 +83,12 @@ zink_get_name(struct pipe_screen *pscreen)
return buf;
}
+static bool
+equals_ivci(const void *a, const void *b)
+{
+ return memcmp(a, b, sizeof(VkImageViewCreateInfo)) == 0;
+}
+
static VkDeviceSize
get_video_mem(struct zink_screen *screen)
{
@@ -846,6 +852,14 @@ zink_destroy_screen(struct pipe_screen *pscreen)
screen->vk_DestroyDebugUtilsMessengerEXT(screen->instance, screen->debugUtilsCallbackHandle, NULL);
}
+ hash_table_foreach(&screen->surface_cache, entry) {
+ struct pipe_surface *psurf = (struct pipe_surface*)entry->data;
+ pipe_resource_reference(&psurf->texture, NULL);
+ pipe_surface_reference(&psurf, NULL);
+ }
+
+ simple_mtx_destroy(&screen->surface_mtx);
+
u_transfer_helper_destroy(pscreen->transfer_helper);
zink_screen_update_pipeline_cache(screen);
#ifdef ENABLE_SHADER_CACHE
@@ -1368,6 +1382,10 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
screen->total_mem = get_video_mem(screen);
+ simple_mtx_init(&screen->surface_mtx, mtx_plain);
+
+ _mesa_hash_table_init(&screen->surface_cache, screen, NULL, equals_ivci);
+
return screen;
fail:
diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h
index afbd43d930c..a7d00f00c91 100644
--- a/src/gallium/drivers/zink/zink_screen.h
+++ b/src/gallium/drivers/zink/zink_screen.h
@@ -54,6 +54,9 @@ struct zink_screen {
struct sw_winsys *winsys;
+ struct hash_table surface_cache;
+ simple_mtx_t surface_mtx;
+
struct slab_parent_pool transfer_pool;
VkPipelineCache pipeline_cache;
size_t pipeline_cache_size;
diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c
index 08dc360ee0e..eaaa28879cc 100644
--- a/src/gallium/drivers/zink/zink_surface.c
+++ b/src/gallium/drivers/zink/zink_surface.c
@@ -30,36 +30,16 @@
#include "util/u_inlines.h"
#include "util/u_memory.h"
-static struct pipe_surface *
-zink_create_surface(struct pipe_context *pctx,
- struct pipe_resource *pres,
- const struct pipe_surface *templ)
+VkImageViewCreateInfo
+create_ivci(struct zink_screen *screen,
+ struct zink_resource *res,
+ const struct pipe_surface *templ)
{
- struct zink_screen *screen = zink_screen(pctx->screen);
- unsigned int level = templ->u.tex.level;
-
- struct zink_surface *surface = CALLOC_STRUCT(zink_surface);
- if (!surface)
- return NULL;
-
- pipe_resource_reference(&surface->base.texture, pres);
- pipe_reference_init(&surface->base.reference, 1);
- surface->base.context = pctx;
- surface->base.format = templ->format;
- surface->base.width = u_minify(pres->width0, level);
- surface->base.height = u_minify(pres->height0, level);
- surface->base.nr_samples = templ->nr_samples;
- surface->base.u.tex.level = level;
- surface->base.u.tex.first_layer = templ->u.tex.first_layer;
- surface->base.u.tex.last_layer = templ->u.tex.last_layer;
-
- struct zink_resource *res = zink_resource(pres);
-
VkImageViewCreateInfo ivci = {};
ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
ivci.image = res->image;
- switch (pres->target) {
+ switch (res->base.target) {
case PIPE_TEXTURE_1D:
ivci.viewType = VK_IMAGE_VIEW_TYPE_1D;
break;
@@ -118,21 +98,105 @@ zink_create_surface(struct pipe_context *pctx,
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
}
- if (vkCreateImageView(screen->dev, &ivci, NULL,
+ return ivci;
+}
+
+static struct zink_surface *
+create_surface(struct pipe_context *pctx,
+ struct pipe_resource *pres,
+ const struct pipe_surface *templ,
+ VkImageViewCreateInfo *ivci)
+{
+ struct zink_screen *screen = zink_screen(pctx->screen);
+ unsigned int level = templ->u.tex.level;
+
+ struct zink_surface *surface = CALLOC_STRUCT(zink_surface);
+ if (!surface)
+ return NULL;
+
+ pipe_resource_reference(&surface->base.texture, pres);
+ pipe_reference_init(&surface->base.reference, 1);
+ surface->base.context = pctx;
+ surface->base.format = templ->format;
+ surface->base.width = u_minify(pres->width0, level);
+ surface->base.height = u_minify(pres->height0, level);
+ surface->base.nr_samples = templ->nr_samples;
+ surface->base.u.tex.level = level;
+ surface->base.u.tex.first_layer = templ->u.tex.first_layer;
+ surface->base.u.tex.last_layer = templ->u.tex.last_layer;
+
+ if (vkCreateImageView(screen->dev, ivci, NULL,
&surface->image_view) != VK_SUCCESS) {
FREE(surface);
return NULL;
}
+ return surface;
+}
+
+static uint32_t
+hash_ivci(const void *key)
+{
+ return _mesa_hash_data((char*)key + offsetof(VkImageViewCreateInfo, flags), sizeof(VkImageViewCreateInfo) - offsetof(VkImageViewCreateInfo, flags));
+}
+
+struct pipe_surface *
+zink_get_surface(struct zink_context *ctx,
+ struct pipe_resource *pres,
+ const struct pipe_surface *templ,
+ VkImageViewCreateInfo *ivci)
+{
+ struct zink_screen *screen = zink_screen(ctx->base.screen);
+ struct zink_surface *surface = NULL;
+ uint32_t hash = hash_ivci(ivci);
+
+ simple_mtx_lock(&screen->surface_mtx);
+ struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(&screen->surface_cache, hash, ivci);
+
+ if (!entry) {
+ /* create a new surface */
+ surface = create_surface(&ctx->base, pres, templ, ivci);
+ surface->hash = hash;
+ surface->ivci = *ivci;
+ entry = _mesa_hash_table_insert_pre_hashed(&screen->surface_cache, hash, &surface->ivci, surface);
+ if (!entry) {
+ simple_mtx_unlock(&screen->surface_mtx);
+ return NULL;
+ }
+
+ surface = entry->data;
+ } else {
+ surface = entry->data;
+ p_atomic_inc(&surface->base.reference.count);
+ }
+ simple_mtx_unlock(&screen->surface_mtx);
+
return &surface->base;
}
+static struct pipe_surface *
+zink_create_surface(struct pipe_context *pctx,
+ struct pipe_resource *pres,
+ const struct pipe_surface *templ)
+{
+
+ VkImageViewCreateInfo ivci = create_ivci(zink_screen(pctx->screen),
+ zink_resource(pres), templ);
+
+ return zink_get_surface(zink_context(pctx), pres, templ, &ivci);
+}
+
static void
zink_surface_destroy(struct pipe_context *pctx,
struct pipe_surface *psurface)
{
struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_surface *surface = zink_surface(psurface);
+ simple_mtx_lock(&screen->surface_mtx);
+ struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&screen->surface_cache, surface->hash, &surface->ivci);
+ assert(he);
+ _mesa_hash_table_remove(&screen->surface_cache, he);
+ simple_mtx_unlock(&screen->surface_mtx);
pipe_resource_reference(&psurface->texture, NULL);
vkDestroyImageView(screen->dev, surface->image_view, NULL);
FREE(surface);
diff --git a/src/gallium/drivers/zink/zink_surface.h b/src/gallium/drivers/zink/zink_surface.h
index a85a4981c20..7cba720ddbd 100644
--- a/src/gallium/drivers/zink/zink_surface.h
+++ b/src/gallium/drivers/zink/zink_surface.h
@@ -32,7 +32,9 @@ struct pipe_context;
struct zink_surface {
struct pipe_surface base;
+ VkImageViewCreateInfo ivci;
VkImageView image_view;
+ uint32_t hash;
};
static inline struct zink_surface *
@@ -44,4 +46,16 @@ zink_surface(struct pipe_surface *pipe)
void
zink_context_surface_init(struct pipe_context *context);
+VkImageViewCreateInfo
+create_ivci(struct zink_screen *screen,
+ struct zink_resource *res,
+ const struct pipe_surface *templ);
+
+struct pipe_surface *
+zink_get_surface(struct zink_context *ctx,
+ struct pipe_resource *pres,
+ const struct pipe_surface *templ,
+ VkImageViewCreateInfo *ivci);
+
+
#endif
More information about the mesa-commit
mailing list