mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 14:08:05 +02:00
fd: allow limiting RD dumps to specific frames and submits
RD dump generation can be expensive and can only be desired for some specific part of execution. Trigger file mechanism helps with this to a certain degree but is still somewhat inexact. FD_RD_DUMP_SUBMITS environment variable can be used to specify ranges of submit indices for which RD dumps of command streams should be generated. FD_RD_DUMP_FRAMES environment variable can similarly be used to specify ranges of frames under which RD dumps for submitted command streams should be generated. Frame ranges only really work with Turnip since the frame count data is available there. Signed-off-by: Zan Dobersek <zdobersek@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37499>
This commit is contained in:
parent
19b3237408
commit
27c16c46fd
5 changed files with 110 additions and 6 deletions
|
|
@ -409,6 +409,11 @@ Output dump files and trigger file (when enabled) are hard-coded to be placed
|
|||
under ``/tmp``, or ``/data/local/tmp`` under Android. `FD_RD_DUMP_TESTNAME` can
|
||||
be used to specify a more descriptive prefix for the output or trigger files.
|
||||
|
||||
Dumping can be limited to specific ranges of frames or submits. For example,
|
||||
``FD_RD_DUMP_SUBMITS=120-140,160,165`` will dump command streams only for the
|
||||
specified submits. Similarly, ``FD_RD_DUMP_FRAMES`` can be set to specify for
|
||||
which frames any submitted command stream should be dumped.
|
||||
|
||||
Functionality is generic to any Freedreno-based backend, but is currently only
|
||||
integrated in the MSM backend of Turnip. Using the existing ``TU_DEBUG=rd``
|
||||
option will translate to ``FD_RD_DUMP=enable``.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -35,6 +36,11 @@ static const struct debug_control fd_rd_dump_options[] = {
|
|||
|
||||
struct fd_rd_dump_env fd_rd_dump_env;
|
||||
|
||||
struct fd_rd_dump_range {
|
||||
unsigned range_begin;
|
||||
unsigned range_end;
|
||||
};
|
||||
|
||||
static void
|
||||
fd_rd_dump_env_init_once(void)
|
||||
{
|
||||
|
|
@ -69,6 +75,81 @@ fd_rd_output_sanitize_name(char *name)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fd_rd_parse_dump_range(const char *option_name, struct util_dynarray *range_array)
|
||||
{
|
||||
util_dynarray_init(range_array, NULL);
|
||||
const char *range_value = os_get_option(option_name);
|
||||
if (!range_value)
|
||||
return;
|
||||
|
||||
const char *p = range_value;
|
||||
while (p && *p) {
|
||||
char *ep = NULL;
|
||||
|
||||
struct fd_rd_dump_range range;
|
||||
range.range_begin = strtol(p, &ep, 0);
|
||||
if (ep == p)
|
||||
break;
|
||||
p = ep;
|
||||
|
||||
range.range_end = range.range_begin;
|
||||
if (*p == '-') {
|
||||
ep = NULL;
|
||||
range.range_end = strtol(++p, &ep, 0);
|
||||
if (ep == p)
|
||||
break;
|
||||
p = ep;
|
||||
}
|
||||
|
||||
util_dynarray_append(range_array, struct fd_rd_dump_range, range);
|
||||
|
||||
if (*p == ',')
|
||||
++p;
|
||||
if (!isdigit(*p) && !!*p)
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '\0') {
|
||||
mesa_logi("[fd_rd_output] %s specified %" PRIuPTR " dump ranges:",
|
||||
option_name, util_dynarray_num_elements(range_array, struct fd_rd_dump_range));
|
||||
util_dynarray_foreach(range_array, struct fd_rd_dump_range, range) {
|
||||
mesa_logi("[fd_rd_output] [%u, %u]", range->range_begin, range->range_end);
|
||||
}
|
||||
} else {
|
||||
mesa_logi("[fd_rd_output] failed to parse dump range '%s' for %s",
|
||||
range_value, option_name);
|
||||
|
||||
util_dynarray_clear(range_array);
|
||||
struct fd_rd_dump_range invalid_range = {
|
||||
.range_begin = UINT_MAX,
|
||||
.range_end = UINT_MAX,
|
||||
};
|
||||
util_dynarray_append(range_array, struct fd_rd_dump_range, invalid_range);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
fd_rd_output_allowed(struct fd_rd_output *output, uint32_t frame, uint32_t submit)
|
||||
{
|
||||
/* Allow output if no ranges were specified. */
|
||||
if (!util_dynarray_num_elements(&output->frame_ranges, struct fd_rd_dump_range) &&
|
||||
!util_dynarray_num_elements(&output->submit_ranges, struct fd_rd_dump_range))
|
||||
return true;
|
||||
|
||||
util_dynarray_foreach(&output->frame_ranges, struct fd_rd_dump_range, range) {
|
||||
if (frame >= range->range_begin && frame <= range->range_end)
|
||||
return true;
|
||||
}
|
||||
|
||||
util_dynarray_foreach(&output->submit_ranges, struct fd_rd_dump_range, range) {
|
||||
if (submit >= range->range_begin && submit <= range->range_end)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
fd_rd_output_init(struct fd_rd_output *output, const char* output_name)
|
||||
{
|
||||
|
|
@ -101,6 +182,9 @@ fd_rd_output_init(struct fd_rd_output *output, const char* output_name)
|
|||
fd_rd_output_base_path, output->name);
|
||||
output->trigger_fd = open(file_path, O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||
}
|
||||
|
||||
fd_rd_parse_dump_range("FD_RD_DUMP_FRAMES", &output->frame_ranges);
|
||||
fd_rd_parse_dump_range("FD_RD_DUMP_SUBMITS", &output->submit_ranges);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -125,6 +209,9 @@ fd_rd_output_fini(struct fd_rd_output *output)
|
|||
fd_rd_output_base_path, output->name);
|
||||
unlink(file_path);
|
||||
}
|
||||
|
||||
util_dynarray_fini(&output->frame_ranges);
|
||||
util_dynarray_fini(&output->submit_ranges);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -193,7 +280,7 @@ fd_rd_output_update_trigger_count(struct fd_rd_output *output)
|
|||
}
|
||||
|
||||
bool
|
||||
fd_rd_output_begin(struct fd_rd_output *output, uint32_t submit_idx)
|
||||
fd_rd_output_begin(struct fd_rd_output *output, uint32_t frame, uint32_t submit)
|
||||
{
|
||||
assert(output->combine ^ (output->file == NULL));
|
||||
|
||||
|
|
@ -207,12 +294,20 @@ fd_rd_output_begin(struct fd_rd_output *output, uint32_t submit_idx)
|
|||
--output->trigger_count;
|
||||
}
|
||||
|
||||
if (!fd_rd_output_allowed(output, frame, submit))
|
||||
return false;
|
||||
|
||||
if (output->combine)
|
||||
return true;
|
||||
|
||||
char file_path[PATH_MAX];
|
||||
snprintf(file_path, sizeof(file_path), "%s/%s_%.5d.rd",
|
||||
fd_rd_output_base_path, output->name, submit_idx);
|
||||
if (frame != UINT_MAX) {
|
||||
snprintf(file_path, sizeof(file_path), "%s/%s_frame%.5d_submit%.5d.rd",
|
||||
fd_rd_output_base_path, output->name, frame, submit);
|
||||
} else {
|
||||
snprintf(file_path, sizeof(file_path), "%s/%s_submit%.5d.rd",
|
||||
fd_rd_output_base_path, output->name, submit);
|
||||
}
|
||||
output->file = gzopen(file_path, "w");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <zlib.h>
|
||||
|
||||
#include "redump.h"
|
||||
#include "util/u_dynarray.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -41,6 +42,9 @@ struct fd_rd_output {
|
|||
|
||||
int trigger_fd;
|
||||
uint32_t trigger_count;
|
||||
|
||||
struct util_dynarray frame_ranges;
|
||||
struct util_dynarray submit_ranges;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -50,7 +54,7 @@ void
|
|||
fd_rd_output_fini(struct fd_rd_output *output);
|
||||
|
||||
bool
|
||||
fd_rd_output_begin(struct fd_rd_output *output, uint32_t submit_idx);
|
||||
fd_rd_output_begin(struct fd_rd_output *output, uint32_t frame, uint32_t submit_idx);
|
||||
|
||||
void
|
||||
fd_rd_output_write_section(struct fd_rd_output *output, enum rd_sect_type type,
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ msm_dump_rd(struct fd_pipe *pipe, struct drm_msm_gem_submit *req)
|
|||
struct fd_rd_output *rd = &pipe->dev->rd;
|
||||
|
||||
if (!fd_rd_dump_env.flags || !req->nr_cmds ||
|
||||
!fd_rd_output_begin(rd, req->fence))
|
||||
!fd_rd_output_begin(rd, UINT_MAX, req->fence))
|
||||
return;
|
||||
|
||||
if (FD_RD_DUMP(FULL)) {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ queue_submit(struct vk_queue *_queue, struct vk_queue_submit *vk_submit)
|
|||
|
||||
if (cmdbuf_count && FD_RD_DUMP(ENABLE) &&
|
||||
fd_rd_output_begin(&queue->device->rd_output,
|
||||
queue->device->submit_count)) {
|
||||
queue->device->vk.current_frame, queue->device->submit_count)) {
|
||||
struct tu_device *device = queue->device;
|
||||
struct fd_rd_output *rd_output = &device->rd_output;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue