mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-10 10:20:20 +01:00
zink: track resource_object usage instead of resource usage
the resource object is now a state tracker for the inner resource_object, so it can safely be destroyed even if the backing resource is still in use this also requires updating various things to keep descriptor states/caches working Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9544>
This commit is contained in:
parent
708f19317c
commit
616720d6ae
8 changed files with 75 additions and 44 deletions
|
|
@ -28,8 +28,8 @@ zink_reset_batch(struct zink_context *ctx, struct zink_batch *batch)
|
|||
|
||||
/* unref all used resources */
|
||||
set_foreach(batch->resources, entry) {
|
||||
struct pipe_resource *pres = (struct pipe_resource *)entry->key;
|
||||
pipe_resource_reference(&pres, NULL);
|
||||
struct zink_resource_object *obj = (struct zink_resource_object *)entry->key;
|
||||
zink_resource_object_reference(screen, &obj, NULL);
|
||||
_mesa_set_remove(batch->resources, entry);
|
||||
}
|
||||
|
||||
|
|
@ -199,12 +199,12 @@ zink_batch_reference_resource_rw(struct zink_batch *batch, struct zink_resource
|
|||
uint32_t check_mask = (ZINK_RESOURCE_ACCESS_READ | ZINK_RESOURCE_ACCESS_WRITE) << batch->batch_id;
|
||||
if (!(uses_check & check_mask)) {
|
||||
bool found = false;
|
||||
_mesa_set_search_and_add(batch->resources, res, &found);
|
||||
_mesa_set_search_and_add(batch->resources, res->obj, &found);
|
||||
if (!found) {
|
||||
pipe_reference(NULL, &res->base.reference);
|
||||
pipe_reference(NULL, &res->obj->reference);
|
||||
batch->resource_size += res->obj->size;
|
||||
if (stencil) {
|
||||
pipe_reference(NULL, &stencil->base.reference);
|
||||
pipe_reference(NULL, &stencil->obj->reference);
|
||||
batch->resource_size += stencil->obj->size;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,10 +215,10 @@ zink_batch_reference_resource_rw(struct zink_batch *batch, struct zink_resource
|
|||
/* the batch_uses value for this batch is guaranteed to not be in use now because
|
||||
* zink_reset_batch() waits on the fence and removes access before resetting
|
||||
*/
|
||||
res->batch_uses[batch->batch_id] |= mask;
|
||||
res->obj->batch_uses[batch->batch_id] |= mask;
|
||||
|
||||
if (stencil)
|
||||
stencil->batch_uses[batch->batch_id] |= mask;
|
||||
stencil->obj->batch_uses[batch->batch_id] |= mask;
|
||||
|
||||
batch->has_work = true;
|
||||
return batch_to_flush;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@
|
|||
static uint32_t
|
||||
calc_descriptor_state_hash_ubo(struct zink_context *ctx, struct zink_shader *zs, enum pipe_shader_type shader, int i, int idx, uint32_t hash)
|
||||
{
|
||||
hash = XXH32(&ctx->ubos[shader][idx].buffer, sizeof(void*), hash);
|
||||
struct zink_resource *res = zink_resource(ctx->ubos[shader][idx].buffer);
|
||||
struct zink_resource_object *obj = res ? res->obj : NULL;
|
||||
hash = XXH32(&obj, sizeof(void*), hash);
|
||||
void *hash_data = &ctx->ubos[shader][idx].buffer_size;
|
||||
size_t data_size = sizeof(unsigned);
|
||||
hash = XXH32(hash_data, data_size, hash);
|
||||
|
|
@ -69,9 +71,15 @@ calc_descriptor_state_hash_ubo(struct zink_context *ctx, struct zink_shader *zs,
|
|||
static uint32_t
|
||||
calc_descriptor_state_hash_ssbo(struct zink_context *ctx, struct zink_shader *zs, enum pipe_shader_type shader, int i, int idx, uint32_t hash)
|
||||
{
|
||||
void *hash_data = &ctx->ssbos[shader][idx];
|
||||
size_t data_size = sizeof(struct pipe_shader_buffer);
|
||||
return XXH32(hash_data, data_size, hash);
|
||||
struct zink_resource *res = zink_resource(ctx->ssbos[shader][idx].buffer);
|
||||
struct zink_resource_object *obj = res ? res->obj : NULL;
|
||||
hash = XXH32(&obj, sizeof(void*), hash);
|
||||
if (obj) {
|
||||
struct pipe_shader_buffer *ssbo = &ctx->ssbos[shader][idx];
|
||||
hash = XXH32(&ssbo->buffer_offset, sizeof(ssbo->buffer_offset), hash);
|
||||
hash = XXH32(&ssbo->buffer_size, sizeof(ssbo->buffer_size), hash);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -137,7 +145,7 @@ calc_descriptor_state_hash_image(struct zink_context *ctx, struct zink_shader *z
|
|||
|
||||
for (unsigned k = 0; k < zs->bindings[ZINK_DESCRIPTOR_TYPE_IMAGE][i].size; k++) {
|
||||
if (!ctx->image_views[shader][idx + k].base.resource) {
|
||||
VkDescriptorImageInfo null_info = {VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED};
|
||||
VkDescriptorImageInfo null_info = {0};
|
||||
hash_data = &null_info;
|
||||
data_size = sizeof(VkDescriptorImageInfo);
|
||||
hash = XXH32(hash_data, data_size, hash);
|
||||
|
|
|
|||
|
|
@ -220,8 +220,8 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink
|
|||
struct zink_descriptor_set *alloc = ralloc_array(pool, struct zink_descriptor_set, bucket_size);
|
||||
assert(alloc);
|
||||
unsigned num_resources = pool->num_resources;
|
||||
struct zink_resource **resources = rzalloc_array(pool, struct zink_resource*, num_resources * bucket_size);
|
||||
assert(resources);
|
||||
struct zink_resource_object **res_objs = rzalloc_array(pool, struct zink_resource_object*, num_resources * bucket_size);
|
||||
assert(res_objs);
|
||||
void **samplers = NULL;
|
||||
if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
|
||||
samplers = rzalloc_array(pool, void*, num_resources * bucket_size);
|
||||
|
|
@ -246,10 +246,10 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink
|
|||
zds->num_resources = num_resources;
|
||||
#endif
|
||||
if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
|
||||
zds->sampler_views = (struct zink_sampler_view**)&resources[i * pool->key.num_descriptors];
|
||||
zds->sampler_views = (struct zink_sampler_view**)&res_objs[i * pool->key.num_descriptors];
|
||||
zds->sampler_states = (struct zink_sampler_state**)&samplers[i * pool->key.num_descriptors];
|
||||
} else
|
||||
zds->resources = (struct zink_resource**)&resources[i * pool->key.num_descriptors];
|
||||
zds->res_objs = (struct zink_resource_object**)&res_objs[i * pool->key.num_descriptors];
|
||||
zds->desc_set = desc_set[i];
|
||||
if (i > 0)
|
||||
util_dynarray_append(&pool->alloc_desc_sets, struct zink_descriptor_set *, zds);
|
||||
|
|
@ -448,7 +448,7 @@ zink_sampler_view_desc_set_add(struct zink_sampler_view *sampler_view, struct zi
|
|||
void
|
||||
zink_resource_desc_set_add(struct zink_resource *res, struct zink_descriptor_set *zds, unsigned idx)
|
||||
{
|
||||
desc_set_ref_add(zds, &res->desc_set_refs, (void**)&zds->resources[idx], res);
|
||||
desc_set_ref_add(zds, res ? &res->obj->desc_set_refs : NULL, (void**)&zds->res_objs[idx], res ? res->obj : NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ struct zink_descriptor_set {
|
|||
unsigned num_resources;
|
||||
#endif
|
||||
union {
|
||||
struct zink_resource **resources;
|
||||
struct zink_resource_object **res_objs;
|
||||
struct zink_image_view **image_views;
|
||||
struct {
|
||||
struct zink_sampler_view **sampler_views;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ desc_set_res_add(struct zink_descriptor_set *zds, struct zink_resource *res, uns
|
|||
* hash table on every resource with the associated descriptor sets that then needs to be iterated through
|
||||
* whenever a resource is destroyed
|
||||
*/
|
||||
assert(!cache_hit || zds->resources[i] == res);
|
||||
assert(!cache_hit || zds->res_objs[i] == (res ? res->obj : NULL));
|
||||
if (!cache_hit)
|
||||
zink_resource_desc_set_add(res, zds, i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,9 +81,9 @@ zink_fence_init(struct zink_fence *fence, struct zink_batch *batch)
|
|||
/* the fence needs its own reference to ensure it can safely access lifetime-dependent
|
||||
* resource members
|
||||
*/
|
||||
struct pipe_resource *r = NULL, *pres = (struct pipe_resource *)entry->key;
|
||||
pipe_resource_reference(&r, pres);
|
||||
util_dynarray_append(&fence->resources, struct pipe_resource*, pres);
|
||||
struct zink_resource_object *obj = (struct zink_resource_object *)entry->key;
|
||||
pipe_reference(NULL, &obj->reference);
|
||||
util_dynarray_append(&fence->resources, struct zink_resource_object*, obj);
|
||||
}
|
||||
fence->deferred_ctx = NULL;
|
||||
fence->submitted = true;
|
||||
|
|
@ -110,9 +110,9 @@ fence_reference(struct pipe_screen *pscreen,
|
|||
}
|
||||
|
||||
static inline void
|
||||
fence_remove_resource_access(struct zink_fence *fence, struct zink_resource *res)
|
||||
fence_remove_resource_access(struct zink_fence *fence, struct zink_resource_object *obj)
|
||||
{
|
||||
p_atomic_set(&res->batch_uses[fence->batch_id], 0);
|
||||
p_atomic_set(&obj->batch_uses[fence->batch_id], 0);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -139,15 +139,10 @@ zink_fence_finish(struct zink_screen *screen, struct pipe_context *pctx, struct
|
|||
zink_prune_queries(screen, fence);
|
||||
|
||||
/* unref all used resources */
|
||||
util_dynarray_foreach(&fence->resources, struct pipe_resource*, pres) {
|
||||
struct zink_resource *stencil, *res = zink_resource(*pres);
|
||||
fence_remove_resource_access(fence, res);
|
||||
util_dynarray_foreach(&fence->resources, struct zink_resource_object*, obj) {
|
||||
fence_remove_resource_access(fence, *obj);
|
||||
|
||||
/* we still hold a ref, so this doesn't need to be atomic */
|
||||
zink_get_depth_stencil_resources((struct pipe_resource*)res, NULL, &stencil);
|
||||
if (stencil)
|
||||
fence_remove_resource_access(fence, stencil);
|
||||
pipe_resource_reference(pres, NULL);
|
||||
zink_resource_object_reference(screen, obj, NULL);
|
||||
}
|
||||
util_dynarray_clear(&fence->resources);
|
||||
fence->submitted = false;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,13 @@
|
|||
#include "drm-uapi/drm_fourcc.h"
|
||||
#endif
|
||||
|
||||
void
|
||||
debug_describe_zink_resource_object(char *buf, const struct zink_resource_object *ptr)
|
||||
{
|
||||
sprintf(buf, "zink_resource_object");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resource_sync_writes_from_batch_usage(struct zink_context *ctx, uint32_t batch_uses)
|
||||
{
|
||||
|
|
@ -120,14 +127,15 @@ cache_or_free_mem(struct zink_screen *screen, struct zink_resource_object *obj)
|
|||
vkFreeMemory(screen->dev, obj->mem, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
resource_object_destroy(struct zink_screen *screen, struct zink_resource_object *obj)
|
||||
void
|
||||
zink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_object *obj)
|
||||
{
|
||||
if (obj->is_buffer)
|
||||
vkDestroyBuffer(screen->dev, obj->buffer, NULL);
|
||||
else
|
||||
vkDestroyImage(screen->dev, obj->image, NULL);
|
||||
|
||||
zink_descriptor_set_refs_clear(&obj->desc_set_refs, obj);
|
||||
cache_or_free_mem(screen, obj);
|
||||
FREE(obj);
|
||||
}
|
||||
|
|
@ -141,8 +149,7 @@ zink_resource_destroy(struct pipe_screen *pscreen,
|
|||
if (pres->target == PIPE_BUFFER)
|
||||
util_range_destroy(&res->valid_buffer_range);
|
||||
|
||||
zink_descriptor_set_refs_clear(&res->desc_set_refs, res);
|
||||
resource_object_destroy(screen, res->obj);
|
||||
zink_resource_object_reference(screen, &res->obj, NULL);
|
||||
FREE(res);
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +196,8 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
|
|||
VkMemoryRequirements reqs = {};
|
||||
VkMemoryPropertyFlags flags;
|
||||
|
||||
pipe_reference_init(&obj->reference, 1);
|
||||
util_dynarray_init(&obj->desc_set_refs.refs, NULL);
|
||||
if (templ->target == PIPE_BUFFER) {
|
||||
VkBufferCreateInfo bci = {};
|
||||
bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
|
|
@ -498,7 +507,6 @@ resource_create(struct pipe_screen *pscreen,
|
|||
&res->dt_stride);
|
||||
}
|
||||
|
||||
util_dynarray_init(&res->desc_set_refs.refs, NULL);
|
||||
return &res->base;
|
||||
}
|
||||
|
||||
|
|
@ -589,8 +597,8 @@ uint32_t
|
|||
zink_get_resource_usage(struct zink_resource *res)
|
||||
{
|
||||
uint32_t batch_uses = 0;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(res->batch_uses); i++)
|
||||
batch_uses |= p_atomic_read(&res->batch_uses[i]) << i;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(res->obj->batch_uses); i++)
|
||||
batch_uses |= p_atomic_read(&res->obj->batch_uses[i]) << i;
|
||||
return batch_uses;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ struct zink_resource_object {
|
|||
VkDeviceSize offset, size;
|
||||
|
||||
unsigned persistent_maps; //if nonzero, requires vkFlushMappedMemoryRanges during batch use
|
||||
struct zink_descriptor_refs desc_set_refs;
|
||||
|
||||
/* this has to be atomic for fence access, so we can't use a bitmask and make everything neat */
|
||||
uint8_t batch_uses[5]; //ZINK_NUM_BATCHES
|
||||
bool is_buffer;
|
||||
bool host_visible;
|
||||
};
|
||||
|
|
@ -82,11 +86,6 @@ struct zink_resource {
|
|||
|
||||
struct sw_displaytarget *dt;
|
||||
unsigned dt_stride;
|
||||
|
||||
struct zink_descriptor_refs desc_set_refs;
|
||||
|
||||
/* this has to be atomic for fence access, so we can't use a bitmask and make everything neat */
|
||||
uint8_t batch_uses[5]; //ZINK_NUM_BATCHES
|
||||
};
|
||||
|
||||
struct zink_transfer {
|
||||
|
|
@ -122,4 +121,25 @@ zink_get_resource_usage(struct zink_resource *res);
|
|||
|
||||
void
|
||||
zink_resource_desc_set_add(struct zink_resource *res, struct zink_descriptor_set *zds, unsigned idx);
|
||||
|
||||
|
||||
void
|
||||
zink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_object *resource_object);
|
||||
|
||||
void
|
||||
debug_describe_zink_resource_object(char *buf, const struct zink_resource_object *ptr);
|
||||
|
||||
static inline void
|
||||
zink_resource_object_reference(struct zink_screen *screen,
|
||||
struct zink_resource_object **dst,
|
||||
struct zink_resource_object *src)
|
||||
{
|
||||
struct zink_resource_object *old_dst = dst ? *dst : NULL;
|
||||
|
||||
if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, &src->reference,
|
||||
(debug_reference_descriptor)debug_describe_zink_resource_object))
|
||||
zink_destroy_resource_object(screen, old_dst);
|
||||
if (dst) *dst = src;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue