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 <sagar.ghuge@intel.com>
Fixes: 1b55f101 ("anv/bvh: Dump BVH synchronously upon command buffer completion")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39599>
This commit is contained in:
Calder Young 2026-01-27 15:55:08 -08:00 committed by Marge Bot
parent 2f6116e419
commit 95e471e558
6 changed files with 55 additions and 19 deletions

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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);
}
}

View file

@ -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