mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-16 01:08:05 +02:00
intel/ds: Add end_event_dyn() and CREATE_DUAL_EVENT_CALLBACK_DYN macro
Add a separate end_event_dyn() that takes a std::string by value for dynamic event names. The [=] lambda capture deep-copies the string into the closure, avoiding a dangling pointer when the Trace() continuation runs after the caller's stack frame is gone. The existing end_event() with const char* remains for string literals and long-lived pointers (e.g. payload->str), where no copy is needed. CREATE_DUAL_EVENT_CALLBACK_DYN formats the event name via snprintf and passes the result as a std::string to end_event_dyn(). Follow-up patches will use this macro to label events with runtime dimensions. Signed-off-by: Michael Cheng <michael.cheng@intel.com> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41374>
This commit is contained in:
parent
41a3213dca
commit
ecbc6625cf
1 changed files with 114 additions and 0 deletions
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/intel_gem.h"
|
||||
#include "perf/intel_perf.h"
|
||||
|
|
@ -307,6 +308,74 @@ end_event(struct intel_ds_queue *queue, uint64_t ts_ns,
|
|||
stage->start_ns[level] = 0;
|
||||
}
|
||||
|
||||
/* Variant for dynamic event names (for example, names formatted in
|
||||
* stack-local buffers).
|
||||
*
|
||||
* Takes a std::string by value so the [=] lambda capture copies string storage
|
||||
* into the Trace() closure. This avoids dangling pointers when Trace() runs
|
||||
* after the caller's stack frame is gone.
|
||||
*
|
||||
* Keep end_event() with const char* for NULL, string literals, and other
|
||||
* long-lived pointers to avoid std::string construction on the common path.
|
||||
*/
|
||||
static void
|
||||
end_event_dyn(struct intel_ds_queue *queue, uint64_t ts_ns,
|
||||
enum intel_ds_queue_stage stage_id,
|
||||
uint32_t submission_id,
|
||||
uint16_t tracepoint_idx,
|
||||
std::string app_event,
|
||||
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;
|
||||
|
||||
if (queue->stages[stage_id].level == 0)
|
||||
return;
|
||||
|
||||
uint32_t level = --queue->stages[stage_id].level;
|
||||
struct intel_ds_stage *stage = &queue->stages[stage_id];
|
||||
uint64_t start_ns = stage->start_ns[level];
|
||||
|
||||
if (!start_ns)
|
||||
return;
|
||||
|
||||
IntelRenderpassDataSource::Trace([=](IntelRenderpassDataSource::TraceContext tctx) {
|
||||
setup_incremental_state(tctx, device);
|
||||
|
||||
sync_timestamp(tctx, device);
|
||||
|
||||
uint64_t evt_id = device->event_id++;
|
||||
|
||||
uint64_t stage_iid = !app_event.empty() ?
|
||||
tctx.GetDataSourceLocked()->debug_marker_stage(tctx, app_event.c_str()) :
|
||||
device->tracepoint_iids[tracepoint_idx];
|
||||
|
||||
auto packet = tctx.NewTracePacket();
|
||||
|
||||
packet->set_timestamp(start_ns);
|
||||
packet->set_timestamp_clock_id(device->gpu_clock_id);
|
||||
|
||||
assert(ts_ns >= start_ns);
|
||||
|
||||
auto event = packet->set_gpu_render_stage_event();
|
||||
event->set_gpu_id(device->gpu_id);
|
||||
|
||||
event->set_hw_queue_iid(stage->queue_iid);
|
||||
event->set_stage_iid(stage_iid);
|
||||
event->set_context(device->iid);
|
||||
event->set_event_id(evt_id);
|
||||
event->set_duration(ts_ns - start_ns);
|
||||
event->set_submission_id(submission_id);
|
||||
|
||||
if ((payload || indirect_data) && payload_as_extra) {
|
||||
payload_as_extra(event, payload, indirect_data);
|
||||
}
|
||||
});
|
||||
|
||||
stage->start_ns[level] = 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
snprintf_stages(char *buf, size_t buf_size,
|
||||
enum intel_ds_barrier_type type,
|
||||
|
|
@ -462,6 +531,51 @@ extern "C" {
|
|||
&trace_payload_as_extra_intel_end_##event_name); \
|
||||
} \
|
||||
|
||||
/*
|
||||
* Like CREATE_DUAL_EVENT_CALLBACK, but for dynamic event names.
|
||||
*
|
||||
* The name is formatted with snprintf() into a stack-local buffer, copied into
|
||||
* a std::string, and passed by value to end_event_dyn(). That keeps the name
|
||||
* alive in the Trace() lambda closure and avoids dangling stack pointers.
|
||||
*/
|
||||
#define CREATE_DUAL_EVENT_CALLBACK_DYN(event_name, stage, name_fmt, ...) \
|
||||
void \
|
||||
intel_ds_begin_##event_name(struct intel_ds_device *device, \
|
||||
uint64_t ts_ns, \
|
||||
uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
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; \
|
||||
begin_event(flush->queue, ts_ns, stage); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
intel_ds_end_##event_name(struct intel_ds_device *device, \
|
||||
uint64_t ts_ns, \
|
||||
uint16_t tp_idx, \
|
||||
const void *flush_data, \
|
||||
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; \
|
||||
UNUSED const uint32_t *indirect = \
|
||||
(const uint32_t *) indirect_data; \
|
||||
char buf[64]; \
|
||||
std::string name; \
|
||||
if ((name_fmt) != NULL) { \
|
||||
snprintf(buf, sizeof(buf), (name_fmt), ##__VA_ARGS__); \
|
||||
name = buf; \
|
||||
} \
|
||||
end_event_dyn(flush->queue, ts_ns, stage, flush->submission_id, \
|
||||
tp_idx, std::move(name), payload, indirect_data, \
|
||||
(trace_payload_as_extra_func) \
|
||||
&trace_payload_as_extra_intel_end_##event_name); \
|
||||
} \
|
||||
|
||||
CREATE_DUAL_EVENT_CALLBACK(frame, INTEL_DS_QUEUE_STAGE_FRAME)
|
||||
CREATE_DUAL_EVENT_CALLBACK(batch, INTEL_DS_QUEUE_STAGE_CMD_BUFFER)
|
||||
CREATE_DUAL_EVENT_CALLBACK(cmd_buffer, INTEL_DS_QUEUE_STAGE_CMD_BUFFER)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue