anv: add support for command buffer tagging in traces

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/16655>
This commit is contained in:
Lionel Landwerlin 2022-05-22 13:18:42 +03:00 committed by Marge Bot
parent 662e05c9fb
commit 28b15fa9e7
4 changed files with 131 additions and 6 deletions

View file

@ -195,12 +195,15 @@ send_descriptors(IntelRenderpassDataSource::TraceContext &ctx,
PERFETTO_LOG("Sending renderstage descriptors");
device->event_id = 0;
device->current_app_event_iid = device->start_app_event_iids;
u_vector_foreach(queue, &device->queues) {
for (uint32_t s = 0; s < ARRAY_SIZE(queue->stages); s++) {
queue->stages[s].start_ns[0] = 0;
}
}
_mesa_hash_table_clear(device->app_events, NULL);
{
auto packet = ctx.NewTracePacket();
@ -271,13 +274,46 @@ begin_event(struct intel_ds_queue *queue, uint64_t ts_ns,
return;
}
if (level >= (ARRAY_SIZE(queue->stages[stage_id].start_ns) - 1))
return;
queue->stages[stage_id].start_ns[level] = ts_ns;
queue->stages[stage_id].level++;
}
static uint64_t
add_app_event(IntelRenderpassDataSource::TraceContext &tctx,
struct intel_ds_device *device,
const char *app_event)
{
struct hash_entry *entry =
_mesa_hash_table_search(device->app_events, app_event);
if (entry)
return (uint64_t) entry->data;
/* Allocate a new iid for the string */
uint64_t iid = device->current_app_event_iid++;
_mesa_hash_table_insert(device->app_events, app_event, (void*)(uintptr_t)iid);
/* Send the definition of iid/string to perfetto */
{
auto packet = tctx.NewTracePacket();
auto interned_data = packet->set_interned_data();
auto desc = interned_data->add_gpu_specifications();
desc->set_iid(iid);
desc->set_name(app_event);
}
return iid;
}
static void
end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
enum intel_ds_queue_stage stage_id,
uint32_t submission_id, const void* payload = nullptr,
uint32_t submission_id,
const char *app_event,
const void* payload = nullptr,
trace_payload_as_extra_func payload_as_extra = nullptr)
{
struct intel_ds_device *device = queue->device;
@ -310,6 +346,13 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
uint64_t evt_id = device->event_id++;
/* If this is an application event, we might need to generate a new
* stage_iid if not already seen. Otherwise, it's a driver event and we
* have use the internal stage_iid.
*/
uint64_t stage_iid = app_event ?
add_app_event(tctx, queue->device, app_event) : stage->stage_iid;
auto packet = tctx.NewTracePacket();
packet->set_timestamp(start_ns);
@ -321,7 +364,7 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
event->set_gpu_id(queue->device->gpu_id);
event->set_hw_queue_iid(stage->queue_iid);
event->set_stage_iid(stage->stage_iid);
event->set_stage_iid(stage_iid);
event->set_context(queue->device->iid);
event->set_event_id(evt_id);
event->set_duration(ts_ns - start_ns);
@ -403,7 +446,7 @@ extern "C" {
const struct intel_ds_flush_data *flush = \
(const struct intel_ds_flush_data *) flush_data; \
end_event(flush->queue, ts_ns, stage, flush->submission_id, \
payload, \
NULL, payload, \
(trace_payload_as_extra_func) \
&trace_payload_as_extra_intel_end_##event_name); \
} \
@ -430,6 +473,29 @@ CREATE_DUAL_EVENT_CALLBACK(compute, INTEL_DS_QUEUE_STAGE_COMPUTE)
CREATE_DUAL_EVENT_CALLBACK(generate_draws, INTEL_DS_QUEUE_STAGE_GENERATE_DRAWS)
CREATE_DUAL_EVENT_CALLBACK(trace_copy, INTEL_DS_QUEUE_STAGE_BLORP)
void
intel_ds_begin_cmd_buffer_annotation(struct intel_ds_device *device,
uint64_t ts_ns,
const void *flush_data,
const struct trace_intel_begin_cmd_buffer_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_CMD_BUFFER);
}
void
intel_ds_end_cmd_buffer_annotation(struct intel_ds_device *device,
uint64_t ts_ns,
const void *flush_data,
const struct trace_intel_end_cmd_buffer_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_CMD_BUFFER,
flush->submission_id, payload->str, NULL, NULL);
}
void
intel_ds_begin_stall(struct intel_ds_device *device,
uint64_t ts_ns,
@ -450,7 +516,7 @@ intel_ds_end_stall(struct intel_ds_device *device,
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_STALL,
flush->submission_id, payload,
flush->submission_id, NULL, payload,
(trace_payload_as_extra_func)custom_trace_payload_as_extra_end_stall);
}
@ -510,10 +576,10 @@ intel_driver_ds_init_once(void)
}
static once_flag intel_driver_ds_once_flag = ONCE_FLAG_INIT;
static uint64_t iid = 1;
static uint64_t get_iid()
{
static uint64_t iid = 1;
return iid++;
}
@ -541,12 +607,18 @@ intel_ds_device_init(struct intel_ds_device *device,
device->iid = get_iid();
device->api = api;
u_vector_init(&device->queues, 4, sizeof(struct intel_ds_queue));
/* Reserve iids for the application generated events */
device->start_app_event_iids = 1ull << 32;
device->app_events =
_mesa_hash_table_create(NULL, _mesa_hash_string, _mesa_key_string_equal);
}
void
intel_ds_device_fini(struct intel_ds_device *device)
{
u_trace_context_fini(&device->trace_context);
_mesa_hash_table_destroy(device->app_events, NULL);
u_vector_finish(&device->queues);
}

View file

@ -103,9 +103,24 @@ struct intel_ds_device {
/* Unique perfetto identifier for the context */
uint64_t iid;
/* Event ID generator */
/* Event ID generator (manipulate only inside
* IntelRenderpassDataSource::Trace)
*/
uint64_t event_id;
/* Start of unique IID for device generated events */
uint64_t start_app_event_iids;
/* Last app event iid (manipulate only inside
* IntelRenderpassDataSource::Trace)
*/
uint64_t current_app_event_iid;
/* Hash table of application generated events (string -> iid) (manipulate
* only inside IntelRenderpassDataSource::Trace)
*/
struct hash_table *app_events;
struct u_trace_context trace_context;
/* List of intel_ds_queue */

View file

@ -57,6 +57,14 @@ def define_tracepoints(args):
tp_args=[Arg(type='uint8_t', var='level', c_format='%hhu'),],
end_pipelined=False)
# Annotations for Cmd(Begin|End)DebugUtilsLabelEXT
begin_end_tp('cmd_buffer_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=True)
begin_end_tp('xfb',
end_pipelined=False)

View file

@ -23,8 +23,11 @@
#include "anv_private.h"
#include "ds/intel_tracepoints.h"
#include "perf/intel_perf.h"
#include "vulkan/runtime/vk_common_entrypoints.h"
static uint32_t
command_buffers_count_utraces(struct anv_device *device,
uint32_t cmd_buffer_count,
@ -332,3 +335,30 @@ anv_pipe_flush_bit_to_ds_stall_flag(enum anv_pipe_bits bits)
return ret;
}
void anv_CmdBeginDebugUtilsLabelEXT(
VkCommandBuffer _commandBuffer,
const VkDebugUtilsLabelEXT *pLabelInfo)
{
VK_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, _commandBuffer);
vk_common_CmdBeginDebugUtilsLabelEXT(_commandBuffer, pLabelInfo);
trace_intel_begin_cmd_buffer_annotation(&cmd_buffer->trace);
}
void anv_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
{
VK_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, _commandBuffer);
if (cmd_buffer->vk.labels.size > 0) {
const VkDebugUtilsLabelEXT *label =
util_dynarray_top_ptr(&cmd_buffer->vk.labels, VkDebugUtilsLabelEXT);
trace_intel_end_cmd_buffer_annotation(&cmd_buffer->trace,
strlen(label->pLabelName),
label->pLabelName);
}
vk_common_CmdEndDebugUtilsLabelEXT(_commandBuffer);
}