From 1fb12d2cceb3284effb6ea5c280e11c7a77a48df Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 19 Jul 2022 14:36:28 +0200 Subject: [PATCH] radv: use ref counting for VS prologs and PS epilogs With GPL, it will be possible to create VS prologs and PS epilogs from libraries, so reference counting is useful here too. Signed-off-by: Samuel Pitoiset Reviewed-By: Tatsuyuki Ishi Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 2 +- src/amd/vulkan/radv_device.c | 18 +++++++++++++----- src/amd/vulkan/radv_shader.c | 5 +++-- src/amd/vulkan/radv_shader.h | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index f0f2cd44326..aace431a9ec 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -3184,7 +3184,7 @@ lookup_vs_prolog(struct radv_cmd_buffer *cmd_buffer, struct radv_shader *vs_shad prolog = radv_create_vs_prolog(device, &key); uint32_t *key2 = malloc(key_size * 4); if (!prolog || !key2) { - radv_shader_part_destroy(device, prolog); + radv_shader_part_unref(device, prolog); free(key2); u_rwlock_wrunlock(&device->vs_prologs_lock); return NULL; diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 1ec572d6123..488cd5f5ff4 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -3029,16 +3029,24 @@ radv_device_finish_vs_prologs(struct radv_device *device) hash_table_foreach(device->vs_prologs, entry) { free((void *)entry->key); - radv_shader_part_destroy(device, entry->data); + radv_shader_part_unref(device, entry->data); } _mesa_hash_table_destroy(device->vs_prologs, NULL); } - for (unsigned i = 0; i < ARRAY_SIZE(device->simple_vs_prologs); i++) - radv_shader_part_destroy(device, device->simple_vs_prologs[i]); + for (unsigned i = 0; i < ARRAY_SIZE(device->simple_vs_prologs); i++) { + if (!device->simple_vs_prologs[i]) + continue; - for (unsigned i = 0; i < ARRAY_SIZE(device->instance_rate_vs_prologs); i++) - radv_shader_part_destroy(device, device->instance_rate_vs_prologs[i]); + radv_shader_part_unref(device, device->simple_vs_prologs[i]); + } + + for (unsigned i = 0; i < ARRAY_SIZE(device->instance_rate_vs_prologs); i++) { + if (!device->instance_rate_vs_prologs[i]) + continue; + + radv_shader_part_unref(device, device->instance_rate_vs_prologs[i]); + } } VkResult diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 7da2915bf62..9629725b7f1 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -2335,6 +2335,8 @@ upload_shader_part(struct radv_device *device, struct radv_shader_part_binary *b if (!shader_part) return NULL; + shader_part->ref_count = 1; + shader_part->alloc = radv_alloc_shader_memory(device, code_size, NULL); if (!shader_part->alloc) { free(shader_part); @@ -2516,8 +2518,7 @@ radv_shader_destroy(struct radv_device *device, struct radv_shader *shader) void radv_shader_part_destroy(struct radv_device *device, struct radv_shader_part *shader_part) { - if (!shader_part) - return; + assert(shader_part->ref_count == 0); radv_free_shader_memory(device, shader_part->alloc); free(shader_part->disasm_string); diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 16ac499e56b..b224005ec5a 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -513,6 +513,8 @@ struct radv_trap_handler_shader { }; struct radv_shader_part { + uint32_t ref_count; + struct radeon_winsys_bo *bo; union radv_shader_arena_block *alloc; uint32_t rsrc1; @@ -637,6 +639,22 @@ radv_shader_unref(struct radv_device *device, struct radv_shader *shader) radv_shader_destroy(device, shader); } +static inline struct radv_shader_part * +radv_shader_part_ref(struct radv_shader_part *shader_part) +{ + assert(shader_part && shader_part->ref_count >= 1); + p_atomic_inc(&shader_part->ref_count); + return shader_part; +} + +static inline void +radv_shader_part_unref(struct radv_device *device, struct radv_shader_part *shader_part) +{ + assert(shader_part && shader_part->ref_count >= 1); + if (p_atomic_dec_zero(&shader_part->ref_count)) + radv_shader_part_destroy(device, shader_part); +} + static inline unsigned calculate_tess_lds_size(enum amd_gfx_level gfx_level, unsigned tcs_num_input_vertices, unsigned tcs_num_output_vertices, unsigned tcs_num_inputs,