anv: add utrace support for queue debug utils
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Sun, 12 Mar 2023 20:04:22 +0000 (22:04 +0200)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Fri, 24 Mar 2023 07:38:20 +0000 (09:38 +0200)
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22006>

src/intel/ds/intel_driver_ds.cc
src/intel/ds/intel_tracepoints.py
src/intel/vulkan/anv_kmd_backend.h
src/intel/vulkan/anv_private.h
src/intel/vulkan/anv_utrace.c
src/intel/vulkan/i915/anv_batch_chain.c
src/intel/vulkan/i915/anv_batch_chain.h
src/intel/vulkan/i915/anv_kmd_backend.c

index 7f49f9b..8b02de3 100644 (file)
@@ -502,6 +502,29 @@ intel_ds_end_cmd_buffer_annotation(struct intel_ds_device *device,
 }
 
 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,
                      const void *flush_data,
index c437497..8dd55b3 100644 (file)
@@ -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'),],
index b3961cf..f4bff78 100644 (file)
@@ -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);
index 0133b40..a4f3594 100644 (file)
@@ -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;
 };
 
index ebabf0c..5c3110f 100644 (file)
@@ -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);
+}
index 74fcca5..ffe3ca0 100644 (file)
@@ -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);
+}
index e9f6fd1..5e3f14f 100644 (file)
@@ -33,8 +33,12 @@ 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);
 VkResult
index 1b21953..0546958 100644 (file)
@@ -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;
 }