mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-02 14:28:05 +02:00
freedreno/rddecompiler: Add ability to read GPU buffer into file
While running tests, it is be useful to have non-sequenced dumps of certain buffers to see their contents from changes in the decompiled CS. This introduces a function gpu_read_into_file(...) for specifying a file to read a specific GPU buffer into after replaying the CS. Signed-off-by: Mark Collins <mark@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26465>
This commit is contained in:
parent
3c89b2882f
commit
80a319c0b4
3 changed files with 98 additions and 0 deletions
|
|
@ -44,6 +44,7 @@ enum rd_sect_type {
|
|||
RD_CHIP_ID,
|
||||
RD_SHADER_LOG_BUFFER, /* Specifies buffer which has logs from shaders */
|
||||
RD_CP_LOG_BUFFER, /* Specifies buffer which has logs from CP */
|
||||
RD_WRBUFFER, /* Specifies buffer which has data that needs to be written out to a file */
|
||||
};
|
||||
|
||||
/* RD_PARAM types: */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ cs_get_cur_iova(struct cmdstream *cs)
|
|||
return cs->iova + cs->cur * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
struct wrbuf {
|
||||
struct list_head link;
|
||||
|
||||
uint64_t iova;
|
||||
uint64_t size;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct replay_context {
|
||||
void *mem_ctx;
|
||||
|
||||
|
|
@ -59,6 +67,8 @@ struct replay_context {
|
|||
|
||||
struct list_head cs_list;
|
||||
|
||||
struct list_head wrbuf_list;
|
||||
|
||||
struct ir3_compiler *compiler;
|
||||
|
||||
struct hash_table_u64 *compiled_shaders;
|
||||
|
|
@ -165,6 +175,18 @@ rd_write_cs_submit(FILE *out, struct cmdstream *cs)
|
|||
fwrite(packet, sizeof(packet), 1, out);
|
||||
}
|
||||
|
||||
static void
|
||||
rd_write_wrbuffer(FILE *out, struct wrbuf *wrbuf)
|
||||
{
|
||||
uint32_t name_len = strlen(wrbuf->name) + 1;
|
||||
struct rd_section section = {.type = RD_WRBUFFER,
|
||||
.size = (uint32_t)(sizeof(uint32_t) * 2) + name_len};
|
||||
fwrite(§ion, sizeof(section), 1, out);
|
||||
fwrite(&wrbuf->iova, sizeof(uint64_t), 1, out);
|
||||
fwrite(&wrbuf->size, sizeof(uint64_t), 1, out);
|
||||
fwrite(wrbuf->name, sizeof(char), name_len, out);
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage(const char *name)
|
||||
{
|
||||
|
|
@ -225,6 +247,7 @@ replay_context_init(struct replay_context *ctx, struct fd_dev_id *dev_id,
|
|||
|
||||
ctx->mem_ctx = ralloc_context(NULL);
|
||||
list_inithead(&ctx->cs_list);
|
||||
list_inithead(&ctx->wrbuf_list);
|
||||
|
||||
util_vma_heap_init(&ctx->vma, va_start, ROUND_DOWN_TO(va_size, 4096));
|
||||
|
||||
|
|
@ -270,6 +293,10 @@ replay_context_finish(struct replay_context *ctx)
|
|||
}
|
||||
rd_write_cs_submit(out, ctx->submit_cs);
|
||||
|
||||
list_for_each_entry (struct wrbuf, wrbuf, &ctx->wrbuf_list, link) {
|
||||
rd_write_wrbuffer(out, wrbuf);
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
|
|
@ -379,3 +406,17 @@ gpu_print(struct replay_context *ctx, struct cmdstream *_cs, uint64_t iova,
|
|||
|
||||
end_ib();
|
||||
}
|
||||
|
||||
static void
|
||||
gpu_read_into_file(struct replay_context *ctx, struct cmdstream *_cs,
|
||||
uint64_t iova, uint64_t size, const char *name)
|
||||
{
|
||||
struct wrbuf *wrbuf = (struct wrbuf *) calloc(1, sizeof(struct wrbuf));
|
||||
wrbuf->iova = iova;
|
||||
wrbuf->size = size;
|
||||
wrbuf->name = strdup(name);
|
||||
|
||||
assert(wrbuf->iova != 0);
|
||||
|
||||
list_addtail(&wrbuf->link, &ctx->wrbuf_list);
|
||||
}
|
||||
|
|
@ -170,6 +170,12 @@ struct cmdstream {
|
|||
uint64_t size;
|
||||
};
|
||||
|
||||
struct wrbuf {
|
||||
uint64_t iova;
|
||||
uint64_t size;
|
||||
char* name;
|
||||
};
|
||||
|
||||
struct device {
|
||||
int fd;
|
||||
|
||||
|
|
@ -190,6 +196,8 @@ struct device {
|
|||
#ifdef FD_REPLAY_KGSL
|
||||
uint32_t context_id;
|
||||
#endif
|
||||
|
||||
struct u_vector wrbufs;
|
||||
};
|
||||
|
||||
void buffer_mem_free(struct device *dev, struct buffer *buf);
|
||||
|
|
@ -325,6 +333,40 @@ device_print_cp_log(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_dump_wrbuf(struct device *dev)
|
||||
{
|
||||
if (!u_vector_length(&dev->wrbufs))
|
||||
return;
|
||||
|
||||
char buffer_dir[256];
|
||||
snprintf(buffer_dir, sizeof(buffer_dir), "%s/buffers", exename);
|
||||
rmdir(buffer_dir);
|
||||
mkdir(buffer_dir, 0777);
|
||||
|
||||
struct wrbuf *wrbuf;
|
||||
u_vector_foreach(wrbuf, &dev->wrbufs) {
|
||||
char buffer_path[256];
|
||||
snprintf(buffer_path, sizeof(buffer_path), "%s/%s", buffer_dir, wrbuf->name);
|
||||
FILE *f = fopen(buffer_path, "wb");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Error opening %s\n", buffer_path);
|
||||
goto end_it;
|
||||
}
|
||||
|
||||
struct buffer *buf = device_get_buffer(dev, wrbuf->iova);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Error getting buffer for %s\n", buffer_path);
|
||||
goto end_it;
|
||||
}
|
||||
const void *buffer = buf->map + (wrbuf->iova - buf->iova);
|
||||
fwrite(buffer, wrbuf->size, 1, f);
|
||||
|
||||
end_it:
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
#if !FD_REPLAY_KGSL
|
||||
static inline void
|
||||
get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns)
|
||||
|
|
@ -401,6 +443,7 @@ device_create()
|
|||
rb_tree_init(&dev->buffers);
|
||||
util_vma_heap_init(&dev->vma, va_start, ROUND_DOWN_TO(va_size, 4096));
|
||||
u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
|
||||
u_vector_init(&dev->wrbufs, 8, sizeof(struct wrbuf));
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
|
@ -521,6 +564,8 @@ device_submit_cmdstreams(struct device *dev)
|
|||
|
||||
device_print_shader_log(dev);
|
||||
device_print_cp_log(dev);
|
||||
|
||||
device_dump_wrbuf(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -714,6 +759,8 @@ device_submit_cmdstreams(struct device *dev)
|
|||
|
||||
device_print_shader_log(dev);
|
||||
device_print_cp_log(dev);
|
||||
|
||||
device_dump_wrbuf(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -834,6 +881,15 @@ override_cmdstream(struct device *dev, struct cmdstream *cs,
|
|||
parse_addr(ps.buf, ps.sz, &sizedwords, &dev->cp_log_iova);
|
||||
break;
|
||||
}
|
||||
case RD_WRBUFFER: {
|
||||
struct wrbuf *wrbuf = u_vector_add(&dev->wrbufs);
|
||||
uint64_t *p = (uint64_t *)ps.buf;
|
||||
wrbuf->iova = p[0];
|
||||
wrbuf->size = p[1];
|
||||
wrbuf->name = calloc(1, p[2]);
|
||||
memcpy(wrbuf->name, (char *)ps.buf + 3 * sizeof(uint64_t), p[2]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue