diff --git a/src/freedreno/common/freedreno_pm4.h b/src/freedreno/common/freedreno_pm4.h index 5a46c0a8124..8f958953d69 100644 --- a/src/freedreno/common/freedreno_pm4.h +++ b/src/freedreno/common/freedreno_pm4.h @@ -39,6 +39,10 @@ extern "C" { #define CP_TYPE4_PKT 0x40000000 #define CP_TYPE7_PKT 0x70000000 +#define CP_NOP_MESG 0x4D455347 +#define CP_NOP_BEGN 0x4245474E +#define CP_NOP_END 0x454E4400 + /* * Helpers for pm4 pkt header building/parsing: */ diff --git a/src/freedreno/vulkan/tu_cs.c b/src/freedreno/vulkan/tu_cs.c index 2e6f215f49a..0bfb8e3bc17 100644 --- a/src/freedreno/vulkan/tu_cs.c +++ b/src/freedreno/vulkan/tu_cs.c @@ -435,3 +435,71 @@ tu_cs_reset(struct tu_cs *cs) cs->entry_count = 0; } + +void +tu_cs_emit_debug_string(struct tu_cs *cs, const char *string, int len) +{ + assert(cs->mode == TU_CS_MODE_GROW); + + /* max packet size is 0x3fff dwords */ + len = MIN2(len, 0x3fff * 4); + + tu_cs_emit_pkt7(cs, CP_NOP, align(len, 4) / 4); + const uint32_t *buf = (const uint32_t *) string; + + tu_cs_emit_array(cs, buf, len / 4); + buf += len / 4; + len = len % 4; + + /* copy remainder bytes without reading past end of input string */ + if (len > 0) { + uint32_t w = 0; + memcpy(&w, buf, len); + tu_cs_emit(cs, w); + } +} + +void +tu_cs_emit_debug_magic_strv(struct tu_cs *cs, + uint32_t magic, + const char *fmt, + va_list args) +{ + int fmt_len = vsnprintf(NULL, 0, fmt, args); + int len = 4 + fmt_len + 1; + char *string = (char *) malloc(len); + + /* format: \0 */ + *(uint32_t *) string = magic; + vsnprintf(string + 4, fmt_len + 1, fmt, args); + + tu_cs_emit_debug_string(cs, string, len); + free(string); +} + +__attribute__((format(printf, 2, 3))) void +tu_cs_emit_debug_msg(struct tu_cs *cs, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + tu_cs_emit_debug_magic_strv(cs, CP_NOP_MESG, fmt, args); + va_end(args); +} + +void +tu_cs_trace_start(void *cs, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_BEGN, fmt, args); + va_end(args); +} + +void +tu_cs_trace_end(void *cs, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_END, fmt, args); + va_end(args); +} \ No newline at end of file diff --git a/src/freedreno/vulkan/tu_cs.h b/src/freedreno/vulkan/tu_cs.h index 54d1a0b463f..4ba64da40f3 100644 --- a/src/freedreno/vulkan/tu_cs.h +++ b/src/freedreno/vulkan/tu_cs.h @@ -375,6 +375,40 @@ tu_cs_emit_call(struct tu_cs *cs, const struct tu_cs *target) tu_cs_emit_ib(cs, target->entries + i); } +/** + * Emit a CP_NOP with a string tail into the command stream. + */ +void +tu_cs_emit_debug_string(struct tu_cs *cs, const char *string, int len); + +void +tu_cs_emit_debug_magic_strv(struct tu_cs *cs, + uint32_t magic, + const char *fmt, + va_list args); + +__attribute__((format(printf, 2, 3))) void +tu_cs_emit_debug_msg(struct tu_cs *cs, const char *fmt, ...); + +/** + * Emit a single message into the CS that denote the calling function and any + * optional printf-style parameters when utrace markers are enabled. + */ +#define TU_CS_DEBUG_MSG(CS, FORMAT_STRING, ...) \ + do { \ + if (unlikely(u_trace_markers_enabled(&(CS)->device->trace_context))) \ + tu_cs_emit_debug_msg(CS, "%s(" FORMAT_STRING ")", __func__, \ + ## __VA_ARGS__); \ + } while (0) + +typedef struct tu_cs *tu_debug_scope; + +__attribute__((format(printf, 2, 3))) void +tu_cs_trace_start(void *cs, const char *fmt, ...); + +__attribute__((format(printf, 2, 3))) void +tu_cs_trace_end(void *cs, const char *fmt, ...); + /* Helpers for bracketing a large sequence of commands of unknown size inside * a CP_COND_REG_EXEC packet. */ diff --git a/src/freedreno/vulkan/tu_tracepoints.py b/src/freedreno/vulkan/tu_tracepoints.py index 56691b25b60..e3d5da5b766 100644 --- a/src/freedreno/vulkan/tu_tracepoints.py +++ b/src/freedreno/vulkan/tu_tracepoints.py @@ -45,7 +45,8 @@ tu_default_tps = [] # def begin_end_tp(name, args=[], tp_struct=None, tp_print=None, - tp_default_enabled=True): + tp_default_enabled=True, marker_tp=True, + queue_tp=True): global tu_default_tps if tp_default_enabled: tu_default_tps.append(name) @@ -53,11 +54,13 @@ def begin_end_tp(name, args=[], tp_struct=None, tp_print=None, toggle_name=name, args=args, tp_struct=tp_struct, - tp_perfetto='tu_perfetto_start_{0}'.format(name), - tp_print=tp_print) + tp_perfetto='tu_perfetto_start_{0}'.format(name) if queue_tp else None, + tp_print=tp_print if queue_tp else None, + tp_markers='tu_cs_trace_start' if marker_tp else None) Tracepoint('end_{0}'.format(name), toggle_name=name, - tp_perfetto='tu_perfetto_end_{0}'.format(name)) + tp_perfetto='tu_perfetto_end_{0}'.format(name), + tp_markers='tu_cs_trace_end' if marker_tp else None) begin_end_tp('cmd_buffer', args=[ArgStruct(type='const struct tu_cmd_buffer *', var='cmd')],