mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-04 04:50:11 +01:00
zink: implement an extremely dumb resource memory cache
this stores a number (currently 5) of backing allocations for resources for later reuse when creating matching resources because this is on the screen object it requires locking, but this is still far faster than allocating new memory each time Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9540>
This commit is contained in:
parent
6205400612
commit
980a8b3fc0
4 changed files with 90 additions and 6 deletions
|
|
@ -67,6 +67,42 @@ resource_sync_writes_from_batch_id(struct zink_context *ctx, uint32_t batch_uses
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
mem_hash(const void *key)
|
||||
{
|
||||
return _mesa_hash_data(key, sizeof(struct mem_key));
|
||||
}
|
||||
|
||||
static bool
|
||||
mem_equals(const void *a, const void *b)
|
||||
{
|
||||
return !memcmp(a, b, sizeof(struct mem_key));
|
||||
}
|
||||
|
||||
static void
|
||||
cache_or_free_mem(struct zink_screen *screen, struct zink_resource *res)
|
||||
{
|
||||
if (res->mkey.flags) {
|
||||
simple_mtx_lock(&screen->mem_cache_mtx);
|
||||
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(screen->resource_mem_cache, res->mem_hash, &res->mkey);
|
||||
struct util_dynarray *array = he ? (void*)he->data : NULL;
|
||||
if (!array) {
|
||||
struct mem_key *mkey = rzalloc(screen->resource_mem_cache, struct mem_key);
|
||||
memcpy(mkey, &res->mkey, sizeof(struct mem_key));
|
||||
array = rzalloc(screen->resource_mem_cache, struct util_dynarray);
|
||||
util_dynarray_init(array, screen->resource_mem_cache);
|
||||
_mesa_hash_table_insert_pre_hashed(screen->resource_mem_cache, res->mem_hash, mkey, array);
|
||||
}
|
||||
if (util_dynarray_num_elements(array, VkDeviceMemory) < 5) {
|
||||
util_dynarray_append(array, VkDeviceMemory, res->mem);
|
||||
simple_mtx_unlock(&screen->mem_cache_mtx);
|
||||
return;
|
||||
}
|
||||
simple_mtx_unlock(&screen->mem_cache_mtx);
|
||||
}
|
||||
vkFreeMemory(screen->dev, res->mem, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
zink_resource_destroy(struct pipe_screen *pscreen,
|
||||
struct pipe_resource *pres)
|
||||
|
|
@ -81,7 +117,8 @@ zink_resource_destroy(struct pipe_screen *pscreen,
|
|||
|
||||
zink_descriptor_set_refs_clear(&res->desc_set_refs, res);
|
||||
|
||||
vkFreeMemory(screen->dev, res->mem, NULL);
|
||||
cache_or_free_mem(screen, res);
|
||||
|
||||
FREE(res);
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +406,21 @@ resource_create(struct pipe_screen *pscreen,
|
|||
mai.pNext = &memory_wsi_info;
|
||||
}
|
||||
|
||||
if (vkAllocateMemory(screen->dev, &mai, NULL, &res->mem) != VK_SUCCESS) {
|
||||
if (!mai.pNext && !(templ->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)) {
|
||||
res->mkey.reqs = reqs;
|
||||
res->mkey.flags = flags;
|
||||
res->mem_hash = mem_hash(&res->mkey);
|
||||
simple_mtx_lock(&screen->mem_cache_mtx);
|
||||
|
||||
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(screen->resource_mem_cache, res->mem_hash, &res->mkey);
|
||||
struct util_dynarray *array = he ? (void*)he->data : NULL;
|
||||
if (array && util_dynarray_num_elements(array, VkDeviceMemory)) {
|
||||
res->mem = util_dynarray_pop(array, VkDeviceMemory);
|
||||
}
|
||||
simple_mtx_unlock(&screen->mem_cache_mtx);
|
||||
}
|
||||
|
||||
if (!res->mem && vkAllocateMemory(screen->dev, &mai, NULL, &res->mem) != VK_SUCCESS) {
|
||||
debug_printf("vkAllocateMemory failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -877,17 +928,21 @@ static const struct u_transfer_vtbl transfer_vtbl = {
|
|||
.get_stencil = zink_resource_get_separate_stencil,
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
zink_screen_resource_init(struct pipe_screen *pscreen)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(pscreen);
|
||||
pscreen->resource_create = zink_resource_create;
|
||||
pscreen->resource_destroy = zink_resource_destroy;
|
||||
pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, true, false, false);
|
||||
|
||||
if (zink_screen(pscreen)->info.have_KHR_external_memory_fd) {
|
||||
if (screen->info.have_KHR_external_memory_fd) {
|
||||
pscreen->resource_get_handle = zink_resource_get_handle;
|
||||
pscreen->resource_from_handle = zink_resource_from_handle;
|
||||
}
|
||||
simple_mtx_init(&screen->mem_cache_mtx, mtx_plain);
|
||||
screen->resource_mem_cache = _mesa_hash_table_create(NULL, mem_hash, mem_equals);
|
||||
return !!screen->resource_mem_cache;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ struct zink_context;
|
|||
#define ZINK_RESOURCE_ACCESS_READ 1
|
||||
#define ZINK_RESOURCE_ACCESS_WRITE 32
|
||||
|
||||
struct mem_key {
|
||||
VkMemoryRequirements reqs;
|
||||
VkMemoryPropertyFlags flags;
|
||||
};
|
||||
|
||||
struct zink_resource {
|
||||
struct pipe_resource base;
|
||||
|
||||
|
|
@ -62,6 +67,8 @@ struct zink_resource {
|
|||
};
|
||||
};
|
||||
VkDeviceMemory mem;
|
||||
uint32_t mem_hash;
|
||||
struct mem_key mkey;
|
||||
VkDeviceSize offset, size;
|
||||
|
||||
struct sw_displaytarget *dt;
|
||||
|
|
@ -85,7 +92,7 @@ zink_resource(struct pipe_resource *r)
|
|||
return (struct zink_resource *)r;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
zink_screen_resource_init(struct pipe_screen *pscreen);
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "os/os_process.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/format/u_format.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_screen.h"
|
||||
|
|
@ -827,6 +828,15 @@ zink_is_format_supported(struct pipe_screen *pscreen,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
resource_cache_entry_destroy(struct zink_screen *screen, struct hash_entry *he)
|
||||
{
|
||||
struct util_dynarray *array = (void*)he->data;
|
||||
util_dynarray_foreach(array, VkDeviceMemory, mem)
|
||||
vkFreeMemory(screen->dev, *mem, NULL);
|
||||
util_dynarray_fini(array);
|
||||
}
|
||||
|
||||
static void
|
||||
zink_destroy_screen(struct pipe_screen *pscreen)
|
||||
{
|
||||
|
|
@ -843,6 +853,12 @@ zink_destroy_screen(struct pipe_screen *pscreen)
|
|||
disk_cache_wait_for_idle(screen->disk_cache);
|
||||
#endif
|
||||
disk_cache_destroy(screen->disk_cache);
|
||||
simple_mtx_lock(&screen->mem_cache_mtx);
|
||||
hash_table_foreach(screen->resource_mem_cache, he)
|
||||
resource_cache_entry_destroy(screen, he);
|
||||
_mesa_hash_table_destroy(screen->resource_mem_cache, NULL);
|
||||
simple_mtx_unlock(&screen->mem_cache_mtx);
|
||||
simple_mtx_destroy(&screen->mem_cache_mtx);
|
||||
vkDestroyPipelineCache(screen->dev, screen->pipeline_cache, NULL);
|
||||
|
||||
vkDestroyDevice(screen->dev, NULL);
|
||||
|
|
@ -1320,7 +1336,8 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
|
|||
screen->base.flush_frontbuffer = zink_flush_frontbuffer;
|
||||
screen->base.destroy = zink_destroy_screen;
|
||||
|
||||
zink_screen_resource_init(&screen->base);
|
||||
if (!zink_screen_resource_init(&screen->base))
|
||||
goto fail;
|
||||
zink_screen_fence_init(&screen->base);
|
||||
|
||||
zink_screen_init_compiler(screen);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "compiler/nir/nir.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/log.h"
|
||||
#include "util/simple_mtx.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
#endif
|
||||
|
||||
extern uint32_t zink_debug;
|
||||
struct hash_table;
|
||||
|
||||
#define ZINK_DEBUG_NIR 0x1
|
||||
#define ZINK_DEBUG_SPIRV 0x2
|
||||
|
|
@ -58,6 +60,9 @@ struct zink_screen {
|
|||
struct disk_cache *disk_cache;
|
||||
cache_key disk_cache_key;
|
||||
|
||||
simple_mtx_t mem_cache_mtx;
|
||||
struct hash_table *resource_mem_cache;
|
||||
|
||||
unsigned shader_id;
|
||||
|
||||
uint64_t total_mem;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue