anv: add utrace support for queue debug utils

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>
This commit is contained in:
Lionel Landwerlin 2023-03-12 22:04:22 +02:00
parent b868f22b46
commit 9448c2628e
8 changed files with 165 additions and 5 deletions

View file

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

View 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'),],

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

View 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;
};

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

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

View file

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

View 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;
}