From 95e471e558fa487b5ad35844f836caa61cef1c7d Mon Sep 17 00:00:00 2001 From: Calder Young Date: Tue, 27 Jan 2026 15:55:08 -0800 Subject: [PATCH] anv: Avoid dumping BVH before command buffer is submitted Fixes a race condition where a BVH will be dumped before its command buffer is actually submitted if a different command buffer completes between the time the BVH dump is recorded and the time the command buffer is actually submitted. Reviewed-by: Sagar Ghuge Fixes: 1b55f101 ("anv/bvh: Dump BVH synchronously upon command buffer completion") Part-of: --- src/intel/vulkan/anv_batch_chain.c | 15 ++++++++++++++ src/intel/vulkan/anv_cmd_buffer.c | 15 ++++++++++++++ src/intel/vulkan/anv_device.c | 1 - src/intel/vulkan/anv_private.h | 18 ++++++++--------- src/intel/vulkan/anv_util.c | 20 ++++++++++++++----- .../vulkan/genX_acceleration_structure.c | 5 ++--- 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index faa703c5cd8..890d354b4e4 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -1335,6 +1335,16 @@ anv_queue_exec_locked(struct anv_queue *queue, struct anv_device *device = queue->device; VkResult result = VK_SUCCESS; +#if ANV_SUPPORT_RT + /* The application could begin resetting command buffers before the + * submission thread actually reaches anv_dump_bvh_to_files, so we + * have to steal the BVH dump list earlier while we're still certain + * the command buffer is in the pending state. + */ + struct list_head bvh_dumps; + anv_get_pending_bvh_dumps(&bvh_dumps, cmd_buffer_count, cmd_buffers); +#endif + /* We only need to synchronize the main & companion command buffers if we * have a companion command buffer somewhere in the list of command * buffers. @@ -1360,6 +1370,11 @@ anv_queue_exec_locked(struct anv_queue *queue, perf_query_pool, perf_query_pass, utrace_submit); + +#if ANV_SUPPORT_RT + anv_dump_bvh_to_files(queue->device, &bvh_dumps); +#endif + if (result != VK_SUCCESS) return result; diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index a7d817ee88b..12cfd41c7d2 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -184,6 +184,8 @@ anv_create_cmd_buffer(struct vk_command_pool *pool, u_trace_init(&cmd_buffer->trace, &device->ds.trace_context); + list_inithead(&cmd_buffer->bvh_dumps); + *cmd_buffer_out = &cmd_buffer->vk; return VK_SUCCESS; @@ -222,6 +224,12 @@ destroy_cmd_buffer(struct anv_cmd_buffer *cmd_buffer) } u_vector_finish(&cmd_buffer->dynamic_bos); + list_for_each_entry_safe(struct anv_bvh_dump, bvh_dump, + &cmd_buffer->bvh_dumps, link) { + anv_device_release_bo(cmd_buffer->device, bvh_dump->bo); + free(bvh_dump); + } + anv_cmd_state_finish(cmd_buffer); vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer->self_mod_locations); @@ -297,6 +305,13 @@ reset_cmd_buffer(struct anv_cmd_buffer *cmd_buffer, u_trace_fini(&cmd_buffer->trace); u_trace_init(&cmd_buffer->trace, &cmd_buffer->device->ds.trace_context); + + list_for_each_entry_safe(struct anv_bvh_dump, bvh_dump, + &cmd_buffer->bvh_dumps, link) { + anv_device_release_bo(cmd_buffer->device, bvh_dump->bo); + free(bvh_dump); + } + list_inithead(&cmd_buffer->bvh_dumps); } void diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index c6d5cc6de57..c04cee22732 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -517,7 +517,6 @@ VkResult anv_CreateDevice( list_inithead(&device->memory_objects); list_inithead(&device->image_private_objects); - list_inithead(&device->bvh_dumps); if (pthread_mutex_init(&device->mutex, NULL) != 0) { result = vk_error(device, VK_ERROR_INITIALIZATION_FAILED); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index d2968305c74..2556b2d0285 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2565,9 +2565,6 @@ struct anv_device { /** List of anv_image objects with a private binding for implicit CCS */ struct list_head image_private_objects; - /** List of anv_bvh_dump objects that get dumped on cmd buf completion */ - struct list_head bvh_dumps; - /** Memory pool for batch buffers */ struct anv_bo_pool batch_bo_pool; /** Memory pool for utrace timestamp buffers */ @@ -2969,7 +2966,11 @@ VkResult anv_device_wait(struct anv_device *device, struct anv_bo *bo, VkResult anv_device_print_init(struct anv_device *device); void anv_device_print_fini(struct anv_device *device); -void anv_dump_bvh_to_files(struct anv_device *device); +void anv_get_pending_bvh_dumps(struct list_head *list, + uint32_t cmd_buffer_count, + struct anv_cmd_buffer **cmd_buffers); + +void anv_dump_bvh_to_files(struct anv_device *device, struct list_head *list); void anv_wait_for_attach(void); @@ -2998,12 +2999,6 @@ anv_queue_post_submit(struct anv_queue *queue, VkResult submit_result) result = vk_queue_set_lost(&queue->vk, "sync wait failed"); } -#if ANV_SUPPORT_RT - /* The recorded bvh is dumped to files upon command buffer completion */ - if (INTEL_DEBUG_BVH_ANY) - anv_dump_bvh_to_files(queue->device); -#endif - return result; } @@ -4957,6 +4952,9 @@ struct anv_cmd_buffer { struct vk_video_session_parameters *params; } video; + /** List of anv_bvh_dump objects that get dumped on cmd buf completion */ + struct list_head bvh_dumps; + /** * Companion RCS command buffer to support the MSAA operations on compute * queue. diff --git a/src/intel/vulkan/anv_util.c b/src/intel/vulkan/anv_util.c index e1c4cf2c2fe..faf2506aba6 100644 --- a/src/intel/vulkan/anv_util.c +++ b/src/intel/vulkan/anv_util.c @@ -312,15 +312,25 @@ create_bvh_dump_file(struct anv_bvh_dump *bvh) fclose(file); } -void anv_dump_bvh_to_files(struct anv_device *device) +void anv_get_pending_bvh_dumps(struct list_head *list, + uint32_t cmd_buffer_count, + struct anv_cmd_buffer **cmd_buffers) { - /* device->mutex is acquired in anv_queue_submit, so no need to lock here. */ - list_for_each_entry_safe(struct anv_bvh_dump, bvh_dump, &device->bvh_dumps, - link) { + list_inithead(list); + if (INTEL_DEBUG_BVH_ANY) { + for (uint32_t i = 0; i < cmd_buffer_count; ++i) { + list_splicetail(&cmd_buffers[i]->bvh_dumps, list); + list_inithead(&cmd_buffers[i]->bvh_dumps); + } + } +} + +void anv_dump_bvh_to_files(struct anv_device* device, struct list_head *list) +{ + list_for_each_entry_safe(struct anv_bvh_dump, bvh_dump, list, link) { create_bvh_dump_file(bvh_dump); anv_device_release_bo(device, bvh_dump->bo); - list_del(&bvh_dump->link); free(bvh_dump); } } diff --git a/src/intel/vulkan/genX_acceleration_structure.c b/src/intel/vulkan/genX_acceleration_structure.c index 5bcadcb59f6..569f66ca417 100644 --- a/src/intel/vulkan/genX_acceleration_structure.c +++ b/src/intel/vulkan/genX_acceleration_structure.c @@ -110,6 +110,7 @@ add_bvh_dump(struct anv_cmd_buffer *cmd_buffer, enum bvh_dump_type dump_type) { assert(dump_size % 4 == 0); + assert(cmd_buffer->vk.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY); struct anv_device *device = cmd_buffer->device; struct anv_bo *bo = NULL; @@ -143,9 +144,7 @@ add_bvh_dump(struct anv_cmd_buffer *cmd_buffer, vk_barrier_compute_w_to_host_r(vk_command_buffer_to_handle(&cmd_buffer->vk)); genX(cmd_buffer_apply_pipe_flushes)(cmd_buffer); - pthread_mutex_lock(&device->mutex); - list_addtail(&bvh_dump->link, &device->bvh_dumps); - pthread_mutex_unlock(&device->mutex); + list_addtail(&bvh_dump->link, &cmd_buffer->bvh_dumps); } static void