mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2024-11-27 04:04:23 +08:00
u_trace: add support for indirect data
Allows a driver to declare indirect arguments for its tracepoints and pass an address. u_trace will request a copy of the data which should be implemented on the command processor. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Co-Authored-by: Danylo Piliaiev <dpiliaiev@igalia.com> Reviewed-by: Danylo Piliaiev <dpiliaiev@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29944>
This commit is contained in:
parent
cb27b9541b
commit
0a17035b5c
@ -44,6 +44,9 @@ u_trace is controlled by environment variables:
|
||||
|
||||
- For Turnip, ``cffdump`` can be used to view the markers in
|
||||
the trace.
|
||||
``indirects``
|
||||
enables indirect data capture for some of the tracepoints (like
|
||||
indirect draw count or indirect dispatch size)
|
||||
|
||||
.. envvar:: MESA_GPU_TRACEFILE
|
||||
|
||||
|
@ -2521,10 +2521,13 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
|
||||
device->submit_count = 0;
|
||||
u_trace_context_init(&device->trace_context, device,
|
||||
sizeof(uint64_t),
|
||||
0,
|
||||
tu_trace_create_buffer,
|
||||
tu_trace_destroy_buffer,
|
||||
TU_CALLX(device, tu_trace_record_ts),
|
||||
tu_trace_read_ts,
|
||||
NULL,
|
||||
NULL,
|
||||
tu_trace_delete_flush_data);
|
||||
|
||||
tu_breadcrumbs_init(device);
|
||||
|
@ -474,7 +474,8 @@ tu_perfetto_submit(struct tu_device *dev,
|
||||
#define CREATE_EVENT_CALLBACK(event_name, stage_id) \
|
||||
void tu_perfetto_start_##event_name( \
|
||||
struct tu_device *dev, uint64_t ts_ns, uint16_t tp_idx, \
|
||||
const void *flush_data, const struct trace_start_##event_name *payload) \
|
||||
const void *flush_data, const struct trace_start_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
stage_start( \
|
||||
dev, ts_ns, stage_id, NULL, payload, sizeof(*payload), \
|
||||
@ -483,7 +484,8 @@ tu_perfetto_submit(struct tu_device *dev,
|
||||
\
|
||||
void tu_perfetto_end_##event_name( \
|
||||
struct tu_device *dev, uint64_t ts_ns, uint16_t tp_idx, \
|
||||
const void *flush_data, const struct trace_end_##event_name *payload) \
|
||||
const void *flush_data, const struct trace_end_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
stage_end( \
|
||||
dev, ts_ns, stage_id, flush_data, payload, \
|
||||
@ -510,7 +512,8 @@ tu_perfetto_start_cmd_buffer_annotation(
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_start_cmd_buffer_annotation *payload)
|
||||
const struct trace_start_cmd_buffer_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
/* No extra func necessary, the only arg is in the end payload.*/
|
||||
stage_start(dev, ts_ns, CMD_BUFFER_ANNOTATION_STAGE_ID, payload->str, payload,
|
||||
@ -523,7 +526,8 @@ tu_perfetto_end_cmd_buffer_annotation(
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_end_cmd_buffer_annotation *payload)
|
||||
const struct trace_end_cmd_buffer_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
/* Pass the payload string as the app_event, which will appear right on the
|
||||
* event block, rather than as metadata inside.
|
||||
@ -538,7 +542,8 @@ tu_perfetto_start_cmd_buffer_annotation_rp(
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_start_cmd_buffer_annotation_rp *payload)
|
||||
const struct trace_start_cmd_buffer_annotation_rp *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
/* No extra func necessary, the only arg is in the end payload.*/
|
||||
stage_start(dev, ts_ns, CMD_BUFFER_ANNOTATION_RENDER_PASS_STAGE_ID,
|
||||
@ -551,7 +556,8 @@ tu_perfetto_end_cmd_buffer_annotation_rp(
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_end_cmd_buffer_annotation_rp *payload)
|
||||
const struct trace_end_cmd_buffer_annotation_rp *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
/* Pass the payload string as the app_event, which will appear right on the
|
||||
* event block, rather than as metadata inside.
|
||||
|
@ -62,16 +62,22 @@ void
|
||||
u_trace_pipe_context_init(struct u_trace_context *utctx,
|
||||
struct pipe_context *pctx,
|
||||
uint32_t timestamp_size_B,
|
||||
uint32_t max_indirect_size_B,
|
||||
u_trace_record_ts record_timestamp,
|
||||
u_trace_read_ts read_timestamp,
|
||||
u_trace_capture_data capture_data,
|
||||
u_trace_get_data get_data,
|
||||
u_trace_delete_flush_data delete_flush_data)
|
||||
{
|
||||
u_trace_context_init(utctx, pctx,
|
||||
timestamp_size_B,
|
||||
max_indirect_size_B,
|
||||
u_trace_pipe_create_buffer,
|
||||
u_trace_pipe_delete_buffer,
|
||||
record_timestamp,
|
||||
read_timestamp,
|
||||
capture_data,
|
||||
get_data,
|
||||
delete_flush_data);
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,11 @@ void
|
||||
u_trace_pipe_context_init(struct u_trace_context *utctx,
|
||||
struct pipe_context *pctx,
|
||||
uint32_t timestamp_size_B,
|
||||
uint32_t max_indirect_size_B,
|
||||
u_trace_record_ts record_timestamp,
|
||||
u_trace_read_ts read_timestamp,
|
||||
u_trace_capture_data capture_data,
|
||||
u_trace_get_data get_data,
|
||||
u_trace_delete_flush_data delete_flush_data);
|
||||
|
||||
/*
|
||||
|
@ -718,8 +718,11 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen,
|
||||
fd_gpu_tracepoint_config_variable();
|
||||
u_trace_pipe_context_init(&ctx->trace_context, pctx,
|
||||
sizeof(uint64_t),
|
||||
0,
|
||||
fd_trace_record_ts,
|
||||
fd_trace_read_ts,
|
||||
NULL,
|
||||
NULL,
|
||||
fd_trace_delete_flush_data);
|
||||
|
||||
fd_autotune_init(&ctx->autotune, screen->dev);
|
||||
|
@ -357,7 +357,8 @@ fd_perfetto_submit(struct fd_context *ctx)
|
||||
void
|
||||
fd_start_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_render_pass *payload)
|
||||
const struct trace_start_render_pass *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, SURFACE_STAGE_ID);
|
||||
|
||||
@ -378,7 +379,8 @@ fd_start_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_render_pass *payload)
|
||||
const struct trace_end_render_pass *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, SURFACE_STAGE_ID);
|
||||
}
|
||||
@ -386,7 +388,8 @@ fd_end_render_pass(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_binning_ib *payload)
|
||||
const struct trace_start_binning_ib *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, BINNING_STAGE_ID);
|
||||
}
|
||||
@ -394,7 +397,8 @@ fd_start_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_binning_ib *payload)
|
||||
const struct trace_end_binning_ib *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, BINNING_STAGE_ID);
|
||||
}
|
||||
@ -402,7 +406,8 @@ fd_end_binning_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_draw_ib *payload)
|
||||
const struct trace_start_draw_ib *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(
|
||||
pctx, ts_ns,
|
||||
@ -412,7 +417,8 @@ fd_start_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_draw_ib *payload)
|
||||
const struct trace_end_draw_ib *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(
|
||||
pctx, ts_ns,
|
||||
@ -422,7 +428,8 @@ fd_end_draw_ib(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_blit(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_blit *payload)
|
||||
const struct trace_start_blit *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, BLIT_STAGE_ID);
|
||||
}
|
||||
@ -430,7 +437,8 @@ fd_start_blit(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_blit(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_blit *payload)
|
||||
const struct trace_end_blit *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, BLIT_STAGE_ID);
|
||||
}
|
||||
@ -438,7 +446,8 @@ fd_end_blit(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_compute(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_compute *payload)
|
||||
const struct trace_start_compute *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, COMPUTE_STAGE_ID);
|
||||
|
||||
@ -458,7 +467,8 @@ fd_start_compute(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_compute(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_compute *payload)
|
||||
const struct trace_end_compute *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, COMPUTE_STAGE_ID);
|
||||
}
|
||||
@ -466,7 +476,8 @@ fd_end_compute(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_clears(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_clears *payload)
|
||||
const struct trace_start_clears *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, CLEAR_STAGE_ID);
|
||||
}
|
||||
@ -474,7 +485,8 @@ fd_start_clears(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_clears(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_clears *payload)
|
||||
const struct trace_end_clears *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, CLEAR_STAGE_ID);
|
||||
}
|
||||
@ -482,7 +494,8 @@ fd_end_clears(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_tile_loads(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_tile_loads *payload)
|
||||
const struct trace_start_tile_loads *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, TILE_LOAD_STAGE_ID);
|
||||
}
|
||||
@ -490,7 +503,8 @@ fd_start_tile_loads(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_tile_loads(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_tile_loads *payload)
|
||||
const struct trace_end_tile_loads *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, TILE_LOAD_STAGE_ID);
|
||||
}
|
||||
@ -498,7 +512,8 @@ fd_end_tile_loads(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_tile_stores(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_tile_stores *payload)
|
||||
const struct trace_start_tile_stores *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, TILE_STORE_STAGE_ID);
|
||||
}
|
||||
@ -506,7 +521,8 @@ fd_start_tile_stores(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_tile_stores(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_tile_stores *payload)
|
||||
const struct trace_end_tile_stores *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, TILE_STORE_STAGE_ID);
|
||||
}
|
||||
@ -514,7 +530,8 @@ fd_end_tile_stores(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_state_restore(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_state_restore *payload)
|
||||
const struct trace_start_state_restore *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, STATE_RESTORE_STAGE_ID);
|
||||
}
|
||||
@ -522,7 +539,8 @@ fd_start_state_restore(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_state_restore(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_state_restore *payload)
|
||||
const struct trace_end_state_restore *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, STATE_RESTORE_STAGE_ID);
|
||||
}
|
||||
@ -530,7 +548,8 @@ fd_end_state_restore(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_vsc_overflow_test(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_vsc_overflow_test *payload)
|
||||
const struct trace_start_vsc_overflow_test *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, VSC_OVERFLOW_STAGE_ID);
|
||||
}
|
||||
@ -538,7 +557,8 @@ fd_start_vsc_overflow_test(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_vsc_overflow_test(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_vsc_overflow_test *payload)
|
||||
const struct trace_end_vsc_overflow_test *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, VSC_OVERFLOW_STAGE_ID);
|
||||
}
|
||||
@ -546,7 +566,8 @@ fd_end_vsc_overflow_test(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_start_prologue(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_start_prologue *payload)
|
||||
const struct trace_start_prologue *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_start(pctx, ts_ns, PROLOGUE_STAGE_ID);
|
||||
}
|
||||
@ -554,7 +575,8 @@ fd_start_prologue(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
void
|
||||
fd_end_prologue(struct pipe_context *pctx, uint64_t ts_ns,
|
||||
uint16_t tp_idx, const void *flush_data,
|
||||
const struct trace_end_prologue *payload)
|
||||
const struct trace_end_prologue *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
stage_end(pctx, ts_ns, PROLOGUE_STAGE_ID);
|
||||
}
|
||||
|
@ -188,10 +188,13 @@ void iris_utrace_init(struct iris_context *ice)
|
||||
|
||||
u_trace_context_init(&ice->ds.trace_context, &ice->ctx,
|
||||
sizeof(union iris_utrace_timestamp),
|
||||
0,
|
||||
iris_utrace_create_buffer,
|
||||
iris_utrace_delete_buffer,
|
||||
iris_utrace_record_ts,
|
||||
iris_utrace_read_ts,
|
||||
NULL,
|
||||
NULL,
|
||||
iris_utrace_delete_flush_data);
|
||||
|
||||
for (int i = 0; i < IRIS_BATCH_COUNT; i++) {
|
||||
|
@ -260,7 +260,8 @@ extern "C" {
|
||||
#define CREATE_DUAL_EVENT_CALLBACK(event_name, stage) \
|
||||
void si_ds_begin_##event_name(struct si_ds_device *device, uint64_t ts_ns, uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
const struct trace_si_begin_##event_name *payload) \
|
||||
const struct trace_si_begin_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
const struct si_ds_flush_data *flush = (const struct si_ds_flush_data *) flush_data; \
|
||||
begin_event(flush->queue, ts_ns, stage); \
|
||||
@ -268,7 +269,8 @@ void si_ds_begin_##event_name(struct si_ds_device *device, uint64_t ts_ns, uint1
|
||||
\
|
||||
void si_ds_end_##event_name(struct si_ds_device *device, uint64_t ts_ns, uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
const struct trace_si_end_##event_name *payload) \
|
||||
const struct trace_si_end_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
const struct si_ds_flush_data *flush = (const struct si_ds_flush_data *) flush_data; \
|
||||
end_event(flush->queue, ts_ns, stage, flush->submission_id, NULL, payload, \
|
||||
|
@ -61,8 +61,9 @@ void si_utrace_init(struct si_context *sctx)
|
||||
|
||||
si_ds_device_init(&sctx->ds, &sctx->screen->info, gpu_id, AMD_DS_API_OPENGL);
|
||||
u_trace_pipe_context_init(&sctx->ds.trace_context, &sctx->b,
|
||||
sizeof(uint64_t), si_utrace_record_ts,
|
||||
si_utrace_read_ts, si_utrace_delete_flush_data);
|
||||
sizeof(uint64_t), 0, si_utrace_record_ts,
|
||||
si_utrace_read_ts, NULL, NULL,
|
||||
si_utrace_delete_flush_data);
|
||||
|
||||
si_ds_device_init_queue(&sctx->ds, &sctx->ds_queue, "%s", "render");
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ send_descriptors(IntelRenderpassDataSource::TraceContext &ctx,
|
||||
sync_timestamp(ctx, device);
|
||||
}
|
||||
|
||||
typedef void (*trace_payload_as_extra_func)(perfetto::protos::pbzero::GpuRenderStageEvent *, const void*);
|
||||
typedef void (*trace_payload_as_extra_func)(perfetto::protos::pbzero::GpuRenderStageEvent *, const void*, const void *);
|
||||
|
||||
static void
|
||||
begin_event(struct intel_ds_queue *queue, uint64_t ts_ns,
|
||||
@ -258,7 +258,8 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
|
||||
uint32_t submission_id,
|
||||
uint16_t tracepoint_idx,
|
||||
const char *app_event,
|
||||
const void* payload = nullptr,
|
||||
const void *payload = nullptr,
|
||||
const void *indirect_data = nullptr,
|
||||
trace_payload_as_extra_func payload_as_extra = nullptr)
|
||||
{
|
||||
struct intel_ds_device *device = queue->device;
|
||||
@ -280,7 +281,6 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
|
||||
if (!start_ns)
|
||||
return;
|
||||
|
||||
|
||||
IntelRenderpassDataSource::Trace([=](IntelRenderpassDataSource::TraceContext tctx) {
|
||||
if (auto state = tctx.GetIncrementalState(); state->was_cleared) {
|
||||
send_descriptors(tctx, queue->device);
|
||||
@ -317,7 +317,7 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
|
||||
event->set_submission_id(submission_id);
|
||||
|
||||
if (payload && payload_as_extra) {
|
||||
payload_as_extra(event, payload);
|
||||
payload_as_extra(event, payload, indirect_data);
|
||||
}
|
||||
});
|
||||
|
||||
@ -384,7 +384,8 @@ extern "C" {
|
||||
uint64_t ts_ns, \
|
||||
uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
const struct trace_intel_begin_##event_name *payload) \
|
||||
const struct trace_intel_begin_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
const struct intel_ds_flush_data *flush = \
|
||||
(const struct intel_ds_flush_data *) flush_data; \
|
||||
@ -396,12 +397,13 @@ extern "C" {
|
||||
uint64_t ts_ns, \
|
||||
uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
const struct trace_intel_end_##event_name *payload) \
|
||||
const struct trace_intel_end_##event_name *payload, \
|
||||
const void *indirect_data) \
|
||||
{ \
|
||||
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, \
|
||||
tp_idx, NULL, payload, \
|
||||
tp_idx, NULL, payload, indirect_data, \
|
||||
(trace_payload_as_extra_func) \
|
||||
&trace_payload_as_extra_intel_end_##event_name); \
|
||||
} \
|
||||
@ -442,7 +444,8 @@ intel_ds_begin_cmd_buffer_annotation(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_begin_cmd_buffer_annotation *payload)
|
||||
const struct trace_intel_begin_cmd_buffer_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
const struct intel_ds_flush_data *flush =
|
||||
(const struct intel_ds_flush_data *) flush_data;
|
||||
@ -454,12 +457,13 @@ intel_ds_end_cmd_buffer_annotation(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_end_cmd_buffer_annotation *payload)
|
||||
const struct trace_intel_end_cmd_buffer_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
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, tp_idx, payload->str, NULL, NULL);
|
||||
flush->submission_id, tp_idx, payload->str, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -467,7 +471,8 @@ intel_ds_begin_queue_annotation(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_begin_queue_annotation *payload)
|
||||
const struct trace_intel_begin_queue_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
const struct intel_ds_flush_data *flush =
|
||||
(const struct intel_ds_flush_data *) flush_data;
|
||||
@ -479,12 +484,13 @@ intel_ds_end_queue_annotation(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_end_queue_annotation *payload)
|
||||
const struct trace_intel_end_queue_annotation *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
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, tp_idx, payload->str, NULL, NULL);
|
||||
flush->submission_id, tp_idx, payload->str, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -492,7 +498,8 @@ intel_ds_begin_stall(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_begin_stall *payload)
|
||||
const struct trace_intel_begin_stall *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
const struct intel_ds_flush_data *flush =
|
||||
(const struct intel_ds_flush_data *) flush_data;
|
||||
@ -504,12 +511,13 @@ intel_ds_end_stall(struct intel_ds_device *device,
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_intel_end_stall *payload)
|
||||
const struct trace_intel_end_stall *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
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, tp_idx, NULL, payload,
|
||||
flush->submission_id, tp_idx, NULL, payload, indirect_data,
|
||||
(trace_payload_as_extra_func)custom_trace_payload_as_extra_end_stall);
|
||||
}
|
||||
|
||||
|
@ -449,10 +449,13 @@ anv_device_utrace_init(struct anv_device *device)
|
||||
u_trace_context_init(&device->ds.trace_context,
|
||||
&device->ds,
|
||||
device->utrace_timestamp_size,
|
||||
0,
|
||||
anv_utrace_create_buffer,
|
||||
anv_utrace_destroy_buffer,
|
||||
anv_utrace_record_ts,
|
||||
anv_utrace_read_ts,
|
||||
NULL,
|
||||
NULL,
|
||||
anv_utrace_delete_submit);
|
||||
|
||||
for (uint32_t q = 0; q < device->queue_count; q++) {
|
||||
|
@ -282,10 +282,13 @@ anv_device_utrace_init(struct anv_device *device)
|
||||
u_trace_context_init(&device->ds.trace_context,
|
||||
&device->ds,
|
||||
sizeof(uint64_t),
|
||||
0,
|
||||
anv_utrace_create_buffer,
|
||||
anv_utrace_destroy_buffer,
|
||||
anv_utrace_record_ts,
|
||||
anv_utrace_read_ts,
|
||||
NULL,
|
||||
NULL,
|
||||
anv_utrace_delete_flush_data);
|
||||
|
||||
for (uint32_t q = 0; q < device->queue_count; q++) {
|
||||
|
@ -91,6 +91,10 @@ struct u_trace_chunk {
|
||||
*/
|
||||
void *timestamps;
|
||||
|
||||
/* table of indirect data captured by u_trace
|
||||
*/
|
||||
void *indirects;
|
||||
|
||||
/* Array of u_trace_payload_buf referenced by traces[] elements.
|
||||
*/
|
||||
struct u_vector payloads;
|
||||
@ -100,6 +104,7 @@ struct u_trace_chunk {
|
||||
|
||||
struct util_queue_fence fence;
|
||||
|
||||
bool has_indirect;
|
||||
bool last; /* this chunk is last in batch */
|
||||
bool eof; /* this chunk is last in frame, unless frame_nr is set */
|
||||
uint32_t frame_nr; /* frame idx from the driver */
|
||||
@ -124,7 +129,8 @@ struct u_trace_printer {
|
||||
struct u_trace_chunk *chunk,
|
||||
const struct u_trace_event *evt,
|
||||
uint64_t ns,
|
||||
int32_t delta);
|
||||
int32_t delta,
|
||||
const void *indirect);
|
||||
};
|
||||
|
||||
static void
|
||||
@ -156,12 +162,13 @@ print_txt_event(struct u_trace_context *utctx,
|
||||
struct u_trace_chunk *chunk,
|
||||
const struct u_trace_event *evt,
|
||||
uint64_t ns,
|
||||
int32_t delta)
|
||||
int32_t delta,
|
||||
const void *indirect)
|
||||
{
|
||||
if (evt->tp->print) {
|
||||
fprintf(utctx->out, "%016" PRIu64 " %+9d: %s: ", ns, delta,
|
||||
evt->tp->name);
|
||||
evt->tp->print(utctx->out, evt->payload);
|
||||
evt->tp->print(utctx->out, evt->payload, indirect);
|
||||
} else {
|
||||
fprintf(utctx->out, "%016" PRIu64 " %+9d: %s\n", ns, delta,
|
||||
evt->tp->name);
|
||||
@ -228,7 +235,8 @@ print_json_event(struct u_trace_context *utctx,
|
||||
struct u_trace_chunk *chunk,
|
||||
const struct u_trace_event *evt,
|
||||
uint64_t ns,
|
||||
int32_t delta)
|
||||
int32_t delta,
|
||||
const void *indirect)
|
||||
{
|
||||
if (utctx->event_nr != 0)
|
||||
fprintf(utctx->out, ",\n");
|
||||
@ -236,7 +244,7 @@ print_json_event(struct u_trace_context *utctx,
|
||||
fprintf(utctx->out, "\"time_ns\": \"%016" PRIu64 "\",\n", ns);
|
||||
fprintf(utctx->out, "\"params\": {");
|
||||
if (evt->tp->print)
|
||||
evt->tp->print_json(utctx->out, evt->payload);
|
||||
evt->tp->print_json(utctx->out, evt->payload, indirect);
|
||||
fprintf(utctx->out, "}\n}\n");
|
||||
}
|
||||
|
||||
@ -285,6 +293,8 @@ free_chunk(void *ptr)
|
||||
struct u_trace_chunk *chunk = ptr;
|
||||
|
||||
chunk->utctx->delete_buffer(chunk->utctx, chunk->timestamps);
|
||||
if (chunk->indirects)
|
||||
chunk->utctx->delete_buffer(chunk->utctx, chunk->indirects);
|
||||
|
||||
/* Unref payloads attached to this chunk. */
|
||||
struct u_trace_payload_buf **payload;
|
||||
@ -349,6 +359,12 @@ get_chunk(struct u_trace *ut, size_t payload_size)
|
||||
chunk->timestamps =
|
||||
ut->utctx->create_buffer(ut->utctx,
|
||||
chunk->utctx->timestamp_size_bytes * TIMESTAMP_BUF_SIZE);
|
||||
if (chunk->utctx->max_indirect_size_bytes &&
|
||||
(chunk->utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS)) {
|
||||
chunk->indirects =
|
||||
ut->utctx->create_buffer(ut->utctx,
|
||||
chunk->utctx->max_indirect_size_bytes * TIMESTAMP_BUF_SIZE);
|
||||
}
|
||||
chunk->last = true;
|
||||
u_vector_init(&chunk->payloads, 4, sizeof(struct u_trace_payload_buf *));
|
||||
if (payload_size > 0) {
|
||||
@ -369,6 +385,7 @@ static const struct debug_named_value config_control[] = {
|
||||
{ "perfetto", U_TRACE_TYPE_PERFETTO_ENV, "Enable perfetto" },
|
||||
#endif
|
||||
{ "markers", U_TRACE_TYPE_MARKERS, "Enable marker trace" },
|
||||
{ "indirects", U_TRACE_TYPE_INDIRECTS, "Enable indirect data capture" },
|
||||
DEBUG_NAMED_VALUE_END
|
||||
};
|
||||
|
||||
@ -436,10 +453,13 @@ void
|
||||
u_trace_context_init(struct u_trace_context *utctx,
|
||||
void *pctx,
|
||||
uint32_t timestamp_size_bytes,
|
||||
uint32_t max_indirect_size_bytes,
|
||||
u_trace_create_buffer create_buffer,
|
||||
u_trace_delete_buffer delete_buffer,
|
||||
u_trace_record_ts record_timestamp,
|
||||
u_trace_read_ts read_timestamp,
|
||||
u_trace_capture_data capture_data,
|
||||
u_trace_get_data get_data,
|
||||
u_trace_delete_flush_data delete_flush_data)
|
||||
{
|
||||
u_trace_state_init();
|
||||
@ -449,9 +469,12 @@ u_trace_context_init(struct u_trace_context *utctx,
|
||||
utctx->create_buffer = create_buffer;
|
||||
utctx->delete_buffer = delete_buffer;
|
||||
utctx->record_timestamp = record_timestamp;
|
||||
utctx->capture_data = capture_data;
|
||||
utctx->get_data = get_data;
|
||||
utctx->read_timestamp = read_timestamp;
|
||||
utctx->delete_flush_data = delete_flush_data;
|
||||
utctx->timestamp_size_bytes = timestamp_size_bytes;
|
||||
utctx->max_indirect_size_bytes = max_indirect_size_bytes;
|
||||
|
||||
utctx->last_time_ns = 0;
|
||||
utctx->first_time_ns = 0;
|
||||
@ -460,6 +483,8 @@ u_trace_context_init(struct u_trace_context *utctx,
|
||||
utctx->event_nr = 0;
|
||||
utctx->start_of_frame = true;
|
||||
|
||||
utctx->dummy_indirect_data = calloc(1, max_indirect_size_bytes);
|
||||
|
||||
list_inithead(&utctx->flushed_trace_chunks);
|
||||
|
||||
if (utctx->enabled_traces & U_TRACE_TYPE_PRINT) {
|
||||
@ -515,6 +540,8 @@ u_trace_context_fini(struct u_trace_context *utctx)
|
||||
fflush(utctx->out);
|
||||
}
|
||||
|
||||
free (utctx->dummy_indirect_data);
|
||||
|
||||
if (!utctx->queue.jobs)
|
||||
return;
|
||||
util_queue_finish(&utctx->queue);
|
||||
@ -614,14 +641,26 @@ process_chunk(void *job, void *gdata, int thread_index)
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
const void *indirect_data = NULL;
|
||||
if (evt->tp->indirect_sz > 0) {
|
||||
if (utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS) {
|
||||
indirect_data = utctx->get_data(utctx, chunk->indirects,
|
||||
utctx->max_indirect_size_bytes * idx,
|
||||
evt->tp->indirect_sz);
|
||||
} else {
|
||||
indirect_data = utctx->dummy_indirect_data;
|
||||
}
|
||||
}
|
||||
|
||||
if (utctx->out) {
|
||||
utctx->out_printer->event(utctx, chunk, evt, ns, delta);
|
||||
utctx->out_printer->event(utctx, chunk, evt, ns, delta, indirect_data);
|
||||
}
|
||||
#ifdef HAVE_PERFETTO
|
||||
if (evt->tp->perfetto &&
|
||||
(p_atomic_read_relaxed(&utctx->enabled_traces) &
|
||||
U_TRACE_TYPE_PERFETTO_ACTIVE)) {
|
||||
evt->tp->perfetto(utctx->pctx, ns, evt->tp->tp_idx, chunk->flush_data, evt->payload);
|
||||
evt->tp->perfetto(utctx->pctx, ns, evt->tp->tp_idx, chunk->flush_data,
|
||||
evt->payload, indirect_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -782,6 +821,15 @@ u_trace_clone_append(struct u_trace_iterator begin_it,
|
||||
begin_it.ut->utctx->timestamp_size_bytes * to_chunk->num_traces,
|
||||
begin_it.ut->utctx->timestamp_size_bytes * to_copy);
|
||||
|
||||
if (from_chunk->has_indirect) {
|
||||
copy_buffer(begin_it.ut->utctx, cmdstream,
|
||||
from_chunk->indirects,
|
||||
begin_it.ut->utctx->max_indirect_size_bytes * from_idx,
|
||||
to_chunk->indirects,
|
||||
begin_it.ut->utctx->max_indirect_size_bytes * to_chunk->num_traces,
|
||||
begin_it.ut->utctx->max_indirect_size_bytes * to_copy);
|
||||
}
|
||||
|
||||
memcpy(&to_chunk->traces[to_chunk->num_traces],
|
||||
&from_chunk->traces[from_idx],
|
||||
to_copy * sizeof(struct u_trace_event));
|
||||
@ -845,7 +893,10 @@ void *
|
||||
u_trace_appendv(struct u_trace *ut,
|
||||
void *cs,
|
||||
const struct u_tracepoint *tp,
|
||||
unsigned variable_sz)
|
||||
unsigned variable_sz,
|
||||
unsigned n_indirects,
|
||||
const struct u_trace_address *addresses,
|
||||
const uint8_t *indirect_sizes_B)
|
||||
{
|
||||
assert(tp->payload_sz == ALIGN_NPOT(tp->payload_sz, 8));
|
||||
|
||||
@ -865,6 +916,16 @@ u_trace_appendv(struct u_trace *ut,
|
||||
ut->utctx->timestamp_size_bytes * tp_idx,
|
||||
tp->flags);
|
||||
|
||||
if (ut->utctx->enabled_traces & U_TRACE_TYPE_INDIRECTS) {
|
||||
for (unsigned i = 0; i < n_indirects; i++) {
|
||||
ut->utctx->capture_data(ut, cs, chunk->indirects,
|
||||
ut->utctx->max_indirect_size_bytes * tp_idx,
|
||||
addresses[i].bo, addresses[i].offset,
|
||||
indirect_sizes_B[i]);
|
||||
}
|
||||
chunk->has_indirect |= n_indirects > 0;
|
||||
}
|
||||
|
||||
chunk->traces[tp_idx] = (struct u_trace_event) {
|
||||
.tp = tp,
|
||||
.payload = payload,
|
||||
|
@ -79,6 +79,20 @@ struct u_trace_printer;
|
||||
*/
|
||||
#define U_TRACE_NO_TIMESTAMP ((uint64_t) 0)
|
||||
|
||||
/**
|
||||
* Address representation
|
||||
*/
|
||||
struct u_trace_address {
|
||||
/**
|
||||
* Pointer to a buffer object
|
||||
*/
|
||||
void *bo;
|
||||
/**
|
||||
* Offset inside the buffer object or address of bo is NULL
|
||||
*/
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Driver provided callback to create a buffer which will be read by
|
||||
* u_trace_read_ts function.
|
||||
@ -107,6 +121,24 @@ typedef void (*u_trace_record_ts)(struct u_trace *ut,
|
||||
uint64_t offset_B,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* Driver provided callback to capture indirect data.
|
||||
*/
|
||||
typedef void (*u_trace_capture_data)(struct u_trace *ut,
|
||||
void *cs,
|
||||
void *dst_buffer,
|
||||
uint64_t dst_offset_B,
|
||||
void *src_buffer,
|
||||
uint64_t src_offset_B,
|
||||
uint32_t size_B);
|
||||
|
||||
/**
|
||||
* Driver provided callback to read back previously recorded indirect data.
|
||||
*/
|
||||
typedef const void *(*u_trace_get_data)(struct u_trace_context *utctx,
|
||||
void *buffer,
|
||||
uint64_t offset_B,
|
||||
uint32_t size_B);
|
||||
/**
|
||||
* Driver provided callback to read back a previously recorded timestamp.
|
||||
* If necessary, this should block until the GPU has finished writing back
|
||||
@ -130,6 +162,18 @@ typedef uint64_t (*u_trace_read_ts)(struct u_trace_context *utctx,
|
||||
uint64_t offset_B,
|
||||
void *flush_data);
|
||||
|
||||
/**
|
||||
* Driver provided callback to create a buffer which will be read by
|
||||
* u_trace_read_ts function.
|
||||
*/
|
||||
typedef void *(*u_trace_copy_data)(struct u_trace *ut,
|
||||
void *cs,
|
||||
void *dst,
|
||||
uint64_t dst_offset_B,
|
||||
void *src,
|
||||
uint64_t src_offset_B,
|
||||
uint64_t size_B);
|
||||
|
||||
/**
|
||||
* Driver provided callback to delete flush data.
|
||||
*/
|
||||
@ -142,6 +186,7 @@ enum u_trace_type {
|
||||
U_TRACE_TYPE_PERFETTO_ACTIVE = 1u << 2,
|
||||
U_TRACE_TYPE_PERFETTO_ENV = 1u << 3,
|
||||
U_TRACE_TYPE_MARKERS = 1u << 4,
|
||||
U_TRACE_TYPE_INDIRECTS = 1u << 5,
|
||||
|
||||
U_TRACE_TYPE_PRINT_JSON = U_TRACE_TYPE_PRINT | U_TRACE_TYPE_JSON,
|
||||
U_TRACE_TYPE_PERFETTO =
|
||||
@ -170,11 +215,14 @@ struct u_trace_context {
|
||||
|
||||
u_trace_create_buffer create_buffer;
|
||||
u_trace_delete_buffer delete_buffer;
|
||||
u_trace_capture_data capture_data;
|
||||
u_trace_get_data get_data;
|
||||
u_trace_record_ts record_timestamp;
|
||||
u_trace_read_ts read_timestamp;
|
||||
u_trace_delete_flush_data delete_flush_data;
|
||||
|
||||
uint64_t timestamp_size_bytes;
|
||||
uint64_t max_indirect_size_bytes;
|
||||
|
||||
FILE *out;
|
||||
struct u_trace_printer *out_printer;
|
||||
@ -201,6 +249,8 @@ struct u_trace_context {
|
||||
uint32_t event_nr;
|
||||
bool start_of_frame;
|
||||
|
||||
void *dummy_indirect_data;
|
||||
|
||||
/* list of unprocessed trace chunks in fifo order: */
|
||||
struct list_head flushed_trace_chunks;
|
||||
};
|
||||
@ -228,10 +278,13 @@ struct u_trace {
|
||||
void u_trace_context_init(struct u_trace_context *utctx,
|
||||
void *pctx,
|
||||
uint32_t timestamp_size_bytes,
|
||||
uint32_t max_indirect_size_bytes,
|
||||
u_trace_create_buffer create_buffer,
|
||||
u_trace_delete_buffer delete_buffer,
|
||||
u_trace_record_ts record_timestamp,
|
||||
u_trace_read_ts read_timestamp,
|
||||
u_trace_capture_data capture_data,
|
||||
u_trace_get_data get_data,
|
||||
u_trace_delete_flush_data delete_flush_data);
|
||||
void u_trace_context_fini(struct u_trace_context *utctx);
|
||||
|
||||
|
@ -59,6 +59,8 @@ class Tracepoint(object):
|
||||
def needs_storage(a):
|
||||
if a.c_format is None:
|
||||
return False
|
||||
if a.is_indirect:
|
||||
return False
|
||||
return True
|
||||
|
||||
self.name = name
|
||||
@ -81,6 +83,14 @@ class Tracepoint(object):
|
||||
self.has_variable_arg = True
|
||||
break
|
||||
self.tp_print_custom = tp_print
|
||||
|
||||
# Compute the offset of each indirect argument
|
||||
self.indirect_args = [x for x in args if x.is_indirect]
|
||||
indirect_sizes = []
|
||||
for indirect in self.indirect_args:
|
||||
indirect.indirect_offset = ' + '.join(indirect_sizes) if len(indirect_sizes) > 0 else 0
|
||||
indirect_sizes.append(f"sizeof({indirect.type}")
|
||||
|
||||
self.tp_perfetto = tp_perfetto
|
||||
self.tp_markers = tp_markers
|
||||
self.tp_flags = tp_flags
|
||||
@ -105,7 +115,7 @@ class Tracepoint(object):
|
||||
class TracepointArgStruct():
|
||||
"""Represents struct that is being passed as an argument
|
||||
"""
|
||||
def __init__(self, type, var, c_format=None, fields=[]):
|
||||
def __init__(self, type, var, c_format=None, fields=[], is_indirect=False):
|
||||
"""Parameters:
|
||||
|
||||
- type: argument's C type.
|
||||
@ -117,17 +127,25 @@ class TracepointArgStruct():
|
||||
self.type = type
|
||||
self.var = var
|
||||
self.name = var
|
||||
self.is_indirect = is_indirect
|
||||
self.indirect_offset = 0
|
||||
self.is_struct = True
|
||||
self.c_format = c_format
|
||||
self.fields = fields
|
||||
self.to_prim_type = None
|
||||
|
||||
self.func_param = f"{self.type} {self.var}"
|
||||
if self.is_indirect:
|
||||
self.func_param = f"struct u_trace_address {self.var}"
|
||||
else:
|
||||
self.func_param = f"{self.type} {self.var}"
|
||||
|
||||
def value_expr(self, entry_name):
|
||||
ret = None
|
||||
if self.is_struct:
|
||||
ret = ", ".join([f"{entry_name}->{self.name}.{f}" for f in self.fields])
|
||||
if self.is_indirect:
|
||||
ret = ", ".join([f"__{self.name}->{f}" for f in self.fields])
|
||||
else:
|
||||
ret = ", ".join([f"{entry_name}->{self.name}.{f}" for f in self.fields])
|
||||
else:
|
||||
ret = f"{entry_name}->{self.name}"
|
||||
return ret
|
||||
@ -136,7 +154,7 @@ class TracepointArg(object):
|
||||
"""Class that represents either an argument being passed or a field in a struct
|
||||
"""
|
||||
def __init__(self, type, var, c_format=None, name=None, to_prim_type=None,
|
||||
length_arg=None, copy_func=None):
|
||||
length_arg=None, copy_func=None, is_indirect=False):
|
||||
"""Parameters:
|
||||
|
||||
- type: argument's C type.
|
||||
@ -162,8 +180,12 @@ class TracepointArg(object):
|
||||
self.copy_func = copy_func
|
||||
|
||||
self.is_struct = False
|
||||
self.is_indirect = is_indirect
|
||||
self.indirect_offset = 0
|
||||
|
||||
if self.type == "str":
|
||||
if self.is_indirect:
|
||||
pass
|
||||
elif self.type == "str":
|
||||
if self.length_arg and self.length_arg.isdigit():
|
||||
self.struct_member = f"char {self.name}[{length_arg} + 1]"
|
||||
else:
|
||||
@ -171,13 +193,18 @@ class TracepointArg(object):
|
||||
else:
|
||||
self.struct_member = f"{self.type} {self.name}"
|
||||
|
||||
if self.type == "str":
|
||||
if self.is_indirect:
|
||||
self.func_param = f"struct u_trace_address {self.var}"
|
||||
elif self.type == "str":
|
||||
self.func_param = f"const char *{self.var}"
|
||||
else:
|
||||
self.func_param = f"{self.type} {self.var}"
|
||||
|
||||
def value_expr(self, entry_name):
|
||||
ret = f"{entry_name}->{self.name}"
|
||||
if self.is_indirect:
|
||||
ret = f"*__{self.name}"
|
||||
else:
|
||||
ret = f"{entry_name}->{self.name}"
|
||||
if not self.is_struct and self.to_prim_type:
|
||||
ret = self.to_prim_type.format(ret)
|
||||
return ret
|
||||
@ -298,7 +325,8 @@ void ${trace.tp_perfetto}(
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const struct trace_${trace_name} *payload);
|
||||
const struct trace_${trace_name} *payload,
|
||||
const void *indirect_data);
|
||||
#endif
|
||||
% endif
|
||||
void __trace_${trace_name}(
|
||||
@ -416,11 +444,14 @@ ${trace_toggle_name}_config_variable(void)
|
||||
* ${trace_name}
|
||||
*/
|
||||
% if trace.can_generate_print():
|
||||
static void __print_${trace_name}(FILE *out, const void *arg) {
|
||||
static void __print_${trace_name}(FILE *out, const void *arg, const void *indirect) {
|
||||
% if len(trace.tp_struct) > 0:
|
||||
const struct trace_${trace_name} *__entry =
|
||||
(const struct trace_${trace_name} *)arg;
|
||||
% endif
|
||||
% for arg in trace.indirect_args:
|
||||
const ${arg.type} *__${arg.name} = (const ${arg.type} *) ((char *)indirect + ${arg.indirect_offset});
|
||||
% endfor
|
||||
% if trace.tp_print_custom is not None:
|
||||
fprintf(out, "${trace.tp_print_custom[0]}\\n"
|
||||
% for arg in trace.tp_print_custom[1:]:
|
||||
@ -439,11 +470,14 @@ static void __print_${trace_name}(FILE *out, const void *arg) {
|
||||
);
|
||||
}
|
||||
|
||||
static void __print_json_${trace_name}(FILE *out, const void *arg) {
|
||||
static void __print_json_${trace_name}(FILE *out, const void *arg, const void *indirect) {
|
||||
% if len(trace.tp_struct) > 0:
|
||||
const struct trace_${trace_name} *__entry =
|
||||
(const struct trace_${trace_name} *)arg;
|
||||
% endif
|
||||
% for arg in trace.indirect_args:
|
||||
const ${arg.type} *__${arg.var} = (const ${arg.type} *) ((char *)indirect + ${arg.indirect_offset});
|
||||
% endfor
|
||||
% if trace.tp_print_custom is not None:
|
||||
fprintf(out, "\\"unstructured\\": \\"${trace.tp_print_custom[0]}\\""
|
||||
% for arg in trace.tp_print_custom[1:]:
|
||||
@ -475,26 +509,35 @@ __attribute__((format(printf, 3, 4))) void ${trace.tp_markers}(struct u_trace_co
|
||||
static void __emit_label_${trace_name}(struct u_trace_context *utctx, void *cs, struct trace_${trace_name} *entry) {
|
||||
${trace.tp_markers}(utctx, cs, "${trace_name}("
|
||||
% for idx,arg in enumerate(trace.tp_print):
|
||||
% if not arg.is_indirect:
|
||||
"${"," if idx != 0 else ""}${arg.name}=${arg.c_format}"
|
||||
% endif
|
||||
% endfor
|
||||
")"
|
||||
% for arg in trace.tp_print:
|
||||
% if not arg.is_indirect:
|
||||
,${arg.value_expr('entry')}
|
||||
% endif
|
||||
% endfor
|
||||
);
|
||||
}
|
||||
|
||||
% endif
|
||||
static const struct u_tracepoint __tp_${trace_name} = {
|
||||
ALIGN_POT(sizeof(struct trace_${trace_name}), 8), /* keep size 64b aligned */
|
||||
"${trace_name}",
|
||||
ALIGN_POT(sizeof(struct trace_${trace_name}), 8), /* keep size 64b aligned */
|
||||
0
|
||||
% for arg in trace.indirect_args:
|
||||
+ sizeof(${arg.type})
|
||||
% endfor
|
||||
,
|
||||
${0 if len(trace.tp_flags) == 0 else " | ".join(trace.tp_flags)},
|
||||
${index},
|
||||
__print_${trace_name},
|
||||
__print_json_${trace_name},
|
||||
% if trace.tp_perfetto is not None:
|
||||
#ifdef HAVE_PERFETTO
|
||||
(void (*)(void *pctx, uint64_t, uint16_t, const void *, const void *))${trace.tp_perfetto},
|
||||
(void (*)(void *pctx, uint64_t, uint16_t, const void *, const void *, const void *))${trace.tp_perfetto},
|
||||
#endif
|
||||
% endif
|
||||
};
|
||||
@ -509,9 +552,20 @@ void __trace_${trace_name}(
|
||||
% endfor
|
||||
) {
|
||||
struct trace_${trace_name} entry;
|
||||
% if len(trace.indirect_args) > 0:
|
||||
struct u_trace_address indirects[] = {
|
||||
% for arg in trace.indirect_args:
|
||||
${arg.var},
|
||||
% endfor
|
||||
};
|
||||
uint8_t indirect_sizes[] = {
|
||||
% for arg in trace.indirect_args:
|
||||
sizeof(${arg.type}),
|
||||
% endfor
|
||||
};
|
||||
% endif
|
||||
UNUSED struct trace_${trace_name} *__entry =
|
||||
enabled_traces & U_TRACE_TYPE_REQUIRE_QUEUING ?
|
||||
% if trace.has_variable_arg:
|
||||
(struct trace_${trace_name} *)u_trace_appendv(ut, ${"cs," if trace.need_cs_param else "NULL,"} &__tp_${trace_name},
|
||||
0
|
||||
% for arg in trace.tp_struct:
|
||||
@ -519,10 +573,13 @@ void __trace_${trace_name}(
|
||||
+ ${arg.length_arg}
|
||||
% endif
|
||||
% endfor
|
||||
,
|
||||
% if len(trace.indirect_args) > 0:
|
||||
ARRAY_SIZE(indirects), indirects, indirect_sizes
|
||||
% else:
|
||||
0, NULL, NULL
|
||||
% endif
|
||||
) :
|
||||
% else:
|
||||
(struct trace_${trace_name} *)u_trace_append(ut, ${"cs," if trace.need_cs_param else "NULL,"} &__tp_${trace_name}) :
|
||||
% endif
|
||||
&entry;
|
||||
% for arg in trace.tp_struct:
|
||||
% if arg.copy_func is None:
|
||||
@ -625,7 +682,8 @@ UNUSED static const char *${basename}_names[] = {
|
||||
% for trace_name, trace in TRACEPOINTS.items():
|
||||
static void UNUSED
|
||||
trace_payload_as_extra_${trace_name}(perfetto::protos::pbzero::GpuRenderStageEvent *event,
|
||||
const struct trace_${trace_name} *payload)
|
||||
const struct trace_${trace_name} *payload,
|
||||
const void *indirect_data)
|
||||
{
|
||||
% if trace.tp_perfetto is not None and len(trace.tp_print) > 0:
|
||||
char buf[128];
|
||||
@ -635,6 +693,9 @@ trace_payload_as_extra_${trace_name}(perfetto::protos::pbzero::GpuRenderStageEve
|
||||
auto data = event->add_extra_data();
|
||||
data->set_name("${arg.name}");
|
||||
|
||||
% if arg.is_indirect:
|
||||
const ${arg.type}* __${arg.var} = (const ${arg.type}*)((uint8_t *)indirect_data + ${arg.indirect_offset});
|
||||
% endif
|
||||
sprintf(buf, "${arg.c_format}", ${arg.value_expr("payload")});
|
||||
|
||||
data->set_value(buf);
|
||||
|
@ -43,8 +43,15 @@ extern "C" {
|
||||
* Tracepoint descriptor.
|
||||
*/
|
||||
struct u_tracepoint {
|
||||
unsigned payload_sz;
|
||||
const char *name;
|
||||
/**
|
||||
* Size of the CPU data associated with this tracepoint.
|
||||
*/
|
||||
uint16_t payload_sz;
|
||||
/**
|
||||
* Size of the GPU data associated with this tracepoint.
|
||||
*/
|
||||
uint16_t indirect_sz;
|
||||
/**
|
||||
* A bitfield of driver agnostic flags
|
||||
*/
|
||||
@ -56,8 +63,8 @@ struct u_tracepoint {
|
||||
* to event->set_stage_iid().
|
||||
*/
|
||||
uint16_t tp_idx;
|
||||
void (*print)(FILE *out, const void *payload);
|
||||
void (*print_json)(FILE *out, const void *payload);
|
||||
void (*print)(FILE *out, const void *payload, const void *indirect);
|
||||
void (*print_json)(FILE *out, const void *payload, const void *indirect);
|
||||
#ifdef HAVE_PERFETTO
|
||||
/**
|
||||
* Callback to emit a perfetto event, such as render-stage trace
|
||||
@ -66,7 +73,8 @@ struct u_tracepoint {
|
||||
uint64_t ts_ns,
|
||||
uint16_t tp_idx,
|
||||
const void *flush_data,
|
||||
const void *payload);
|
||||
const void *payload,
|
||||
const void *indirect);
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -77,7 +85,10 @@ struct u_tracepoint {
|
||||
void *u_trace_appendv(struct u_trace *ut,
|
||||
void *cs,
|
||||
const struct u_tracepoint *tp,
|
||||
unsigned variable_sz);
|
||||
unsigned variable_sz,
|
||||
unsigned n_indirects,
|
||||
const struct u_trace_address *addresses,
|
||||
const uint8_t *indirect_sizes_B);
|
||||
|
||||
/**
|
||||
* Append a trace event, returning pointer to buffer of tp->payload_sz
|
||||
@ -87,7 +98,7 @@ void *u_trace_appendv(struct u_trace *ut,
|
||||
static inline void *
|
||||
u_trace_append(struct u_trace *ut, void *cs, const struct u_tracepoint *tp)
|
||||
{
|
||||
return u_trace_appendv(ut, cs, tp, 0);
|
||||
return u_trace_appendv(ut, cs, tp, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -11,7 +11,8 @@ static int
|
||||
test_thread(void *_state)
|
||||
{
|
||||
struct u_trace_context ctx = {};
|
||||
u_trace_context_init(&ctx, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
u_trace_context_init(&ctx, NULL, 8, 0, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
u_trace_context_fini(&ctx);
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user