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@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9541>
This commit is contained in:
parent
2643f9ed28
commit
38f7faa8a4
4 changed files with 125 additions and 26 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue