From 9448c2628ebf562db6f77d7e66f48d4ec9fe659f Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Sun, 12 Mar 2023 22:04:22 +0200 Subject: [PATCH] anv: add utrace support for queue debug utils Signed-off-by: Lionel Landwerlin Reviewed-by: Emma Anholt Part-of: --- src/intel/ds/intel_driver_ds.cc | 23 ++++++ src/intel/ds/intel_tracepoints.py | 9 +++ src/intel/vulkan/anv_kmd_backend.h | 3 + src/intel/vulkan/anv_private.h | 16 +++- src/intel/vulkan/anv_utrace.c | 103 +++++++++++++++++++++++- src/intel/vulkan/i915/anv_batch_chain.c | 9 +++ src/intel/vulkan/i915/anv_batch_chain.h | 4 + src/intel/vulkan/i915/anv_kmd_backend.c | 3 +- 8 files changed, 165 insertions(+), 5 deletions(-) diff --git a/src/intel/ds/intel_driver_ds.cc b/src/intel/ds/intel_driver_ds.cc index 7f49f9b9a93..8b02de36bd6 100644 --- a/src/intel/ds/intel_driver_ds.cc +++ b/src/intel/ds/intel_driver_ds.cc @@ -501,6 +501,29 @@ intel_ds_end_cmd_buffer_annotation(struct intel_ds_device *device, flush->submission_id, payload->str, NULL, NULL); } +void +intel_ds_begin_queue_annotation(struct intel_ds_device *device, + uint64_t ts_ns, + const void *flush_data, + const struct trace_intel_begin_queue_annotation *payload) +{ + const struct intel_ds_flush_data *flush = + (const struct intel_ds_flush_data *) flush_data; + begin_event(flush->queue, ts_ns, INTEL_DS_QUEUE_STAGE_QUEUE); +} + +void +intel_ds_end_queue_annotation(struct intel_ds_device *device, + uint64_t ts_ns, + const void *flush_data, + const struct trace_intel_end_queue_annotation *payload) +{ + const struct intel_ds_flush_data *flush = + (const struct intel_ds_flush_data *) flush_data; + end_event(flush->queue, ts_ns, INTEL_DS_QUEUE_STAGE_QUEUE, + flush->submission_id, payload->str, NULL, NULL); +} + void intel_ds_begin_stall(struct intel_ds_device *device, uint64_t ts_ns, diff --git a/src/intel/ds/intel_tracepoints.py b/src/intel/ds/intel_tracepoints.py index c43749717f5..8dd55b3edb9 100644 --- a/src/intel/ds/intel_tracepoints.py +++ b/src/intel/ds/intel_tracepoints.py @@ -68,6 +68,15 @@ def define_tracepoints(args): tp_args=[Arg(type='uint32_t', var='frame', c_format='%u'),], end_pipelined=False) + # Annotations for Queue(Begin|End)DebugUtilsLabelEXT + begin_end_tp('queue_annotation', + tp_args=[ArgStruct(type='unsigned', var='len'), + ArgStruct(type='const char *', var='str'),], + tp_struct=[Arg(type='uint8_t', name='dummy', var='0', c_format='%hhu'), + Arg(type='char', name='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + end_pipelined=False, + need_cs_param=True) + # Batch buffer tracepoints, only for Iris begin_end_tp('batch', tp_args=[Arg(type='uint8_t', var='name', c_format='%hhu'),], diff --git a/src/intel/vulkan/anv_kmd_backend.h b/src/intel/vulkan/anv_kmd_backend.h index b3961cf85b7..f4bff78e91a 100644 --- a/src/intel/vulkan/anv_kmd_backend.h +++ b/src/intel/vulkan/anv_kmd_backend.h @@ -37,6 +37,7 @@ struct anv_cmd_buffer; struct anv_device; struct anv_queue; struct anv_query_pool; +struct anv_utrace_submit; struct anv_kmd_backend { /* @@ -66,6 +67,8 @@ struct anv_kmd_backend { const struct vk_sync_signal *signals, struct anv_query_pool *perf_query_pool, uint32_t perf_query_pass); + VkResult (*queue_exec_trace)(struct anv_queue *queue, + struct anv_utrace_submit *submit); }; const struct anv_kmd_backend *anv_kmd_backend_get(enum intel_kmd_type type); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 0133b40d723..a4f3594d4f6 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -4212,6 +4212,15 @@ anv_device_init_generated_indirect_draws(struct anv_device *device); void anv_device_finish_generated_indirect_draws(struct anv_device *device); +/* This structure is used in 2 scenarios : + * + * - copy utrace timestamps from command buffer so that command buffer can + * be resubmitted multiple times without the recorded timestamps being + * overwritten before they're read back + * + * - emit trace points for queue debug tagging + * (vkQueueBeginDebugUtilsLabelEXT/vkQueueEndDebugUtilsLabelEXT) + */ struct anv_utrace_submit { /* Needs to be the first field */ struct intel_ds_flush_data ds; @@ -4223,15 +4232,16 @@ struct anv_utrace_submit { struct anv_batch batch; struct anv_bo *batch_bo; - /* Buffer of 64bits timestamps */ - struct anv_bo *trace_bo; - /* Syncobj to be signaled when the batch completes */ struct vk_sync *sync; /* Queue on which all the recorded traces are submitted */ struct anv_queue *queue; + /* Buffer of 64bits timestamps (only used for timestamp copies) */ + struct anv_bo *trace_bo; + + /* Memcpy state tracking (only used for timestamp copies) */ struct anv_memcpy_state memcpy_state; }; diff --git a/src/intel/vulkan/anv_utrace.c b/src/intel/vulkan/anv_utrace.c index ebabf0c462f..5c3110f9026 100644 --- a/src/intel/vulkan/anv_utrace.c +++ b/src/intel/vulkan/anv_utrace.c @@ -24,6 +24,7 @@ #include "anv_private.h" #include "ds/intel_tracepoints.h" +#include "genxml/gen8_pack.h" #include "perf/intel_perf.h" #include "vulkan/runtime/vk_common_entrypoints.h" @@ -364,4 +365,104 @@ void anv_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer) } vk_common_CmdEndDebugUtilsLabelEXT(_commandBuffer); - } +} + +static void +anv_queue_trace(struct anv_queue *queue, const VkDebugUtilsLabelEXT *label, bool begin) +{ + struct anv_device *device = queue->device; + + VkResult result; + struct anv_utrace_submit *submit = + vk_zalloc(&device->vk.alloc, sizeof(struct anv_utrace_submit), + 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + if (!submit) + return; + + submit->queue = queue; + + intel_ds_flush_data_init(&submit->ds, &queue->ds, queue->ds.submission_id); + + result = vk_sync_create(&device->vk, &device->physical->sync_syncobj_type, + 0, 0, &submit->sync); + if (result != VK_SUCCESS) + goto error_trace; + + result = anv_bo_pool_alloc(&device->utrace_bo_pool, 4096, + &submit->batch_bo); + if (result != VK_SUCCESS) + goto error_sync; + + result = anv_reloc_list_init(&submit->relocs, &device->vk.alloc); + if (result != VK_SUCCESS) + goto error_batch_bo; + + submit->batch.alloc = &device->vk.alloc; + submit->batch.relocs = &submit->relocs; + anv_batch_set_storage(&submit->batch, + (struct anv_address) { .bo = submit->batch_bo, }, + submit->batch_bo->map, submit->batch_bo->size); + + if (begin) { + trace_intel_begin_queue_annotation(&submit->ds.trace, &submit->batch); + } else { + trace_intel_end_queue_annotation(&submit->ds.trace, + &submit->batch, + strlen(label->pLabelName), + label->pLabelName); + } + + anv_batch_emit(&submit->batch, GFX8_MI_BATCH_BUFFER_END, bbs); + anv_batch_emit(&submit->batch, GFX8_MI_NOOP, noop); + + if (submit->batch.status != VK_SUCCESS) { + result = submit->batch.status; + goto error_reloc_list; + } + + u_trace_flush(&submit->ds.trace, submit, true); + + pthread_mutex_lock(&device->mutex); + device->kmd_backend->queue_exec_trace(queue, submit); + pthread_mutex_unlock(&device->mutex); + + return; + + error_reloc_list: + anv_reloc_list_finish(&submit->relocs, &device->vk.alloc); + error_batch_bo: + anv_bo_pool_free(&device->utrace_bo_pool, submit->batch_bo); + error_sync: + vk_sync_destroy(&device->vk, submit->sync); + error_trace: + intel_ds_flush_data_fini(&submit->ds); + vk_free(&device->vk.alloc, submit); +} + +void +anv_QueueBeginDebugUtilsLabelEXT( + VkQueue _queue, + const VkDebugUtilsLabelEXT *pLabelInfo) +{ + VK_FROM_HANDLE(anv_queue, queue, _queue); + + vk_common_QueueBeginDebugUtilsLabelEXT(_queue, pLabelInfo); + + anv_queue_trace(queue, pLabelInfo, true /* begin */); +} + +void +anv_QueueEndDebugUtilsLabelEXT(VkQueue _queue) +{ + VK_FROM_HANDLE(anv_queue, queue, _queue); + + if (queue->vk.labels.size > 0) { + const VkDebugUtilsLabelEXT *label = + util_dynarray_top_ptr(&queue->vk.labels, VkDebugUtilsLabelEXT); + anv_queue_trace(queue, label, false /* begin */); + + u_trace_context_process(&queue->device->ds.trace_context, true); + } + + vk_common_QueueEndDebugUtilsLabelEXT(_queue); +} diff --git a/src/intel/vulkan/i915/anv_batch_chain.c b/src/intel/vulkan/i915/anv_batch_chain.c index 74fcca5f9a2..ffe3ca07945 100644 --- a/src/intel/vulkan/i915/anv_batch_chain.c +++ b/src/intel/vulkan/i915/anv_batch_chain.c @@ -798,3 +798,12 @@ fail: anv_execbuf_finish(&execbuf); return result; } + +VkResult +i915_queue_exec_trace(struct anv_queue *queue, + struct anv_utrace_submit *submit) +{ + assert(submit->batch_bo); + + return anv_queue_exec_utrace_locked(queue, submit); +} diff --git a/src/intel/vulkan/i915/anv_batch_chain.h b/src/intel/vulkan/i915/anv_batch_chain.h index e9f6fd1e3dc..5e3f14fd00b 100644 --- a/src/intel/vulkan/i915/anv_batch_chain.h +++ b/src/intel/vulkan/i915/anv_batch_chain.h @@ -33,7 +33,11 @@ struct anv_queue; struct anv_bo; struct anv_cmd_buffer; struct anv_query_pool; +struct anv_utrace_submit; +VkResult +i915_queue_exec_trace(struct anv_queue *queue, + struct anv_utrace_submit *submit); VkResult i915_execute_simple_batch(struct anv_queue *queue, struct anv_bo *batch_bo, uint32_t batch_bo_size); diff --git a/src/intel/vulkan/i915/anv_kmd_backend.c b/src/intel/vulkan/i915/anv_kmd_backend.c index 1b21953baaf..0546958d650 100644 --- a/src/intel/vulkan/i915/anv_kmd_backend.c +++ b/src/intel/vulkan/i915/anv_kmd_backend.c @@ -171,7 +171,8 @@ anv_i915_kmd_backend_get(void) .gem_vm_bind = i915_gem_vm_bind, .gem_vm_unbind = i915_gem_vm_unbind, .execute_simple_batch = i915_execute_simple_batch, - .queue_exec_locked = i915_queue_exec_locked + .queue_exec_locked = i915_queue_exec_locked, + .queue_exec_trace = i915_queue_exec_trace, }; return &i915_backend; }