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,