1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "ac_debug.h" 26bf215546Sopenharmony_ci#include "ac_rtld.h" 27bf215546Sopenharmony_ci#include "driver_ddebug/dd_util.h" 28bf215546Sopenharmony_ci#include "si_compute.h" 29bf215546Sopenharmony_ci#include "si_pipe.h" 30bf215546Sopenharmony_ci#include "sid.h" 31bf215546Sopenharmony_ci#include "sid_tables.h" 32bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h" 33bf215546Sopenharmony_ci#include "util/u_dump.h" 34bf215546Sopenharmony_ci#include "util/u_log.h" 35bf215546Sopenharmony_ci#include "util/u_memory.h" 36bf215546Sopenharmony_ci#include "util/u_string.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic void si_dump_bo_list(struct si_context *sctx, const struct radeon_saved_cs *saved, FILE *f); 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ciDEBUG_GET_ONCE_OPTION(replace_shaders, "RADEON_REPLACE_SHADERS", NULL) 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci/** 43bf215546Sopenharmony_ci * Store a linearized copy of all chunks of \p cs together with the buffer 44bf215546Sopenharmony_ci * list in \p saved. 45bf215546Sopenharmony_ci */ 46bf215546Sopenharmony_civoid si_save_cs(struct radeon_winsys *ws, struct radeon_cmdbuf *cs, struct radeon_saved_cs *saved, 47bf215546Sopenharmony_ci bool get_buffer_list) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci uint32_t *buf; 50bf215546Sopenharmony_ci unsigned i; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci /* Save the IB chunks. */ 53bf215546Sopenharmony_ci saved->num_dw = cs->prev_dw + cs->current.cdw; 54bf215546Sopenharmony_ci saved->ib = MALLOC(4 * saved->num_dw); 55bf215546Sopenharmony_ci if (!saved->ib) 56bf215546Sopenharmony_ci goto oom; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci buf = saved->ib; 59bf215546Sopenharmony_ci for (i = 0; i < cs->num_prev; ++i) { 60bf215546Sopenharmony_ci memcpy(buf, cs->prev[i].buf, cs->prev[i].cdw * 4); 61bf215546Sopenharmony_ci buf += cs->prev[i].cdw; 62bf215546Sopenharmony_ci } 63bf215546Sopenharmony_ci memcpy(buf, cs->current.buf, cs->current.cdw * 4); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci if (!get_buffer_list) 66bf215546Sopenharmony_ci return; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci /* Save the buffer list. */ 69bf215546Sopenharmony_ci saved->bo_count = ws->cs_get_buffer_list(cs, NULL); 70bf215546Sopenharmony_ci saved->bo_list = CALLOC(saved->bo_count, sizeof(saved->bo_list[0])); 71bf215546Sopenharmony_ci if (!saved->bo_list) { 72bf215546Sopenharmony_ci FREE(saved->ib); 73bf215546Sopenharmony_ci goto oom; 74bf215546Sopenharmony_ci } 75bf215546Sopenharmony_ci ws->cs_get_buffer_list(cs, saved->bo_list); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci return; 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_cioom: 80bf215546Sopenharmony_ci fprintf(stderr, "%s: out of memory\n", __func__); 81bf215546Sopenharmony_ci memset(saved, 0, sizeof(*saved)); 82bf215546Sopenharmony_ci} 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_civoid si_clear_saved_cs(struct radeon_saved_cs *saved) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci FREE(saved->ib); 87bf215546Sopenharmony_ci FREE(saved->bo_list); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci memset(saved, 0, sizeof(*saved)); 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_civoid si_destroy_saved_cs(struct si_saved_cs *scs) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci si_clear_saved_cs(&scs->gfx); 95bf215546Sopenharmony_ci si_resource_reference(&scs->trace_buf, NULL); 96bf215546Sopenharmony_ci free(scs); 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic void si_dump_shader(struct si_screen *sscreen, struct si_shader *shader, FILE *f) 100bf215546Sopenharmony_ci{ 101bf215546Sopenharmony_ci if (shader->shader_log) 102bf215546Sopenharmony_ci fwrite(shader->shader_log, shader->shader_log_size, 1, f); 103bf215546Sopenharmony_ci else 104bf215546Sopenharmony_ci si_shader_dump(sscreen, shader, NULL, f, false); 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (shader->bo && sscreen->options.dump_shader_binary) { 107bf215546Sopenharmony_ci unsigned size = shader->bo->b.b.width0; 108bf215546Sopenharmony_ci fprintf(f, "BO: VA=%" PRIx64 " Size=%u\n", shader->bo->gpu_address, size); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci const char *mapped = sscreen->ws->buffer_map(sscreen->ws, 111bf215546Sopenharmony_ci shader->bo->buf, NULL, 112bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_READ | RADEON_MAP_TEMPORARY); 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci for (unsigned i = 0; i < size; i += 4) { 115bf215546Sopenharmony_ci fprintf(f, " %4x: %08x\n", i, *(uint32_t *)(mapped + i)); 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci sscreen->ws->buffer_unmap(sscreen->ws, shader->bo->buf); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci fprintf(f, "\n"); 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistruct si_log_chunk_shader { 125bf215546Sopenharmony_ci /* The shader destroy code assumes a current context for unlinking of 126bf215546Sopenharmony_ci * PM4 packets etc. 127bf215546Sopenharmony_ci * 128bf215546Sopenharmony_ci * While we should be able to destroy shaders without a context, doing 129bf215546Sopenharmony_ci * so would happen only very rarely and be therefore likely to fail 130bf215546Sopenharmony_ci * just when you're trying to debug something. Let's just remember the 131bf215546Sopenharmony_ci * current context in the chunk. 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_ci struct si_context *ctx; 134bf215546Sopenharmony_ci struct si_shader *shader; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci /* For keep-alive reference counts */ 137bf215546Sopenharmony_ci struct si_shader_selector *sel; 138bf215546Sopenharmony_ci struct si_compute *program; 139bf215546Sopenharmony_ci}; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_cistatic void si_log_chunk_shader_destroy(void *data) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci struct si_log_chunk_shader *chunk = data; 144bf215546Sopenharmony_ci si_shader_selector_reference(chunk->ctx, &chunk->sel, NULL); 145bf215546Sopenharmony_ci si_compute_reference(&chunk->program, NULL); 146bf215546Sopenharmony_ci FREE(chunk); 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_cistatic void si_log_chunk_shader_print(void *data, FILE *f) 150bf215546Sopenharmony_ci{ 151bf215546Sopenharmony_ci struct si_log_chunk_shader *chunk = data; 152bf215546Sopenharmony_ci struct si_screen *sscreen = chunk->ctx->screen; 153bf215546Sopenharmony_ci si_dump_shader(sscreen, chunk->shader, f); 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic struct u_log_chunk_type si_log_chunk_type_shader = { 157bf215546Sopenharmony_ci .destroy = si_log_chunk_shader_destroy, 158bf215546Sopenharmony_ci .print = si_log_chunk_shader_print, 159bf215546Sopenharmony_ci}; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_cistatic void si_dump_gfx_shader(struct si_context *ctx, const struct si_shader_ctx_state *state, 162bf215546Sopenharmony_ci struct u_log_context *log) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci struct si_shader *current = state->current; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci if (!state->cso || !current) 167bf215546Sopenharmony_ci return; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci struct si_log_chunk_shader *chunk = CALLOC_STRUCT(si_log_chunk_shader); 170bf215546Sopenharmony_ci chunk->ctx = ctx; 171bf215546Sopenharmony_ci chunk->shader = current; 172bf215546Sopenharmony_ci si_shader_selector_reference(ctx, &chunk->sel, current->selector); 173bf215546Sopenharmony_ci u_log_chunk(log, &si_log_chunk_type_shader, chunk); 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_cistatic void si_dump_compute_shader(struct si_context *ctx, struct u_log_context *log) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci const struct si_cs_shader_state *state = &ctx->cs_shader_state; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci if (!state->program) 181bf215546Sopenharmony_ci return; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci struct si_log_chunk_shader *chunk = CALLOC_STRUCT(si_log_chunk_shader); 184bf215546Sopenharmony_ci chunk->ctx = ctx; 185bf215546Sopenharmony_ci chunk->shader = &state->program->shader; 186bf215546Sopenharmony_ci si_compute_reference(&chunk->program, state->program); 187bf215546Sopenharmony_ci u_log_chunk(log, &si_log_chunk_type_shader, chunk); 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci/** 191bf215546Sopenharmony_ci * Shader compiles can be overridden with arbitrary ELF objects by setting 192bf215546Sopenharmony_ci * the environment variable RADEON_REPLACE_SHADERS=num1:filename1[;num2:filename2] 193bf215546Sopenharmony_ci * 194bf215546Sopenharmony_ci * TODO: key this off some hash 195bf215546Sopenharmony_ci */ 196bf215546Sopenharmony_cibool si_replace_shader(unsigned num, struct si_shader_binary *binary) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci const char *p = debug_get_option_replace_shaders(); 199bf215546Sopenharmony_ci const char *semicolon; 200bf215546Sopenharmony_ci char *copy = NULL; 201bf215546Sopenharmony_ci FILE *f; 202bf215546Sopenharmony_ci long filesize, nread; 203bf215546Sopenharmony_ci bool replaced = false; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci if (!p) 206bf215546Sopenharmony_ci return false; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci while (*p) { 209bf215546Sopenharmony_ci unsigned long i; 210bf215546Sopenharmony_ci char *endp; 211bf215546Sopenharmony_ci i = strtoul(p, &endp, 0); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci p = endp; 214bf215546Sopenharmony_ci if (*p != ':') { 215bf215546Sopenharmony_ci fprintf(stderr, "RADEON_REPLACE_SHADERS formatted badly.\n"); 216bf215546Sopenharmony_ci exit(1); 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci ++p; 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci if (i == num) 221bf215546Sopenharmony_ci break; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci p = strchr(p, ';'); 224bf215546Sopenharmony_ci if (!p) 225bf215546Sopenharmony_ci return false; 226bf215546Sopenharmony_ci ++p; 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci if (!*p) 229bf215546Sopenharmony_ci return false; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci semicolon = strchr(p, ';'); 232bf215546Sopenharmony_ci if (semicolon) { 233bf215546Sopenharmony_ci p = copy = strndup(p, semicolon - p); 234bf215546Sopenharmony_ci if (!copy) { 235bf215546Sopenharmony_ci fprintf(stderr, "out of memory\n"); 236bf215546Sopenharmony_ci return false; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci } 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci fprintf(stderr, "radeonsi: replace shader %u by %s\n", num, p); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci f = fopen(p, "r"); 243bf215546Sopenharmony_ci if (!f) { 244bf215546Sopenharmony_ci perror("radeonsi: failed to open file"); 245bf215546Sopenharmony_ci goto out_free; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci if (fseek(f, 0, SEEK_END) != 0) 249bf215546Sopenharmony_ci goto file_error; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci filesize = ftell(f); 252bf215546Sopenharmony_ci if (filesize < 0) 253bf215546Sopenharmony_ci goto file_error; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci if (fseek(f, 0, SEEK_SET) != 0) 256bf215546Sopenharmony_ci goto file_error; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci binary->elf_buffer = MALLOC(filesize); 259bf215546Sopenharmony_ci if (!binary->elf_buffer) { 260bf215546Sopenharmony_ci fprintf(stderr, "out of memory\n"); 261bf215546Sopenharmony_ci goto out_close; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci nread = fread((void *)binary->elf_buffer, 1, filesize, f); 265bf215546Sopenharmony_ci if (nread != filesize) { 266bf215546Sopenharmony_ci FREE((void *)binary->elf_buffer); 267bf215546Sopenharmony_ci binary->elf_buffer = NULL; 268bf215546Sopenharmony_ci goto file_error; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci binary->elf_size = nread; 272bf215546Sopenharmony_ci replaced = true; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ciout_close: 275bf215546Sopenharmony_ci fclose(f); 276bf215546Sopenharmony_ciout_free: 277bf215546Sopenharmony_ci free(copy); 278bf215546Sopenharmony_ci return replaced; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_cifile_error: 281bf215546Sopenharmony_ci perror("radeonsi: reading shader"); 282bf215546Sopenharmony_ci goto out_close; 283bf215546Sopenharmony_ci} 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci/* Parsed IBs are difficult to read without colors. Use "less -R file" to 286bf215546Sopenharmony_ci * read them, or use "aha -b -f file" to convert them to html. 287bf215546Sopenharmony_ci */ 288bf215546Sopenharmony_ci#define COLOR_RESET "\033[0m" 289bf215546Sopenharmony_ci#define COLOR_RED "\033[31m" 290bf215546Sopenharmony_ci#define COLOR_GREEN "\033[1;32m" 291bf215546Sopenharmony_ci#define COLOR_YELLOW "\033[1;33m" 292bf215546Sopenharmony_ci#define COLOR_CYAN "\033[1;36m" 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_cistatic void si_dump_mmapped_reg(struct si_context *sctx, FILE *f, unsigned offset) 295bf215546Sopenharmony_ci{ 296bf215546Sopenharmony_ci struct radeon_winsys *ws = sctx->ws; 297bf215546Sopenharmony_ci uint32_t value; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (ws->read_registers(ws, offset, 1, &value)) 300bf215546Sopenharmony_ci ac_dump_reg(f, sctx->gfx_level, offset, value, ~0); 301bf215546Sopenharmony_ci} 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_cistatic void si_dump_debug_registers(struct si_context *sctx, FILE *f) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci fprintf(f, "Memory-mapped registers:\n"); 306bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008010_GRBM_STATUS); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci /* No other registers can be read on radeon. */ 309bf215546Sopenharmony_ci if (!sctx->screen->info.is_amdgpu) { 310bf215546Sopenharmony_ci fprintf(f, "\n"); 311bf215546Sopenharmony_ci return; 312bf215546Sopenharmony_ci } 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008008_GRBM_STATUS2); 315bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008014_GRBM_STATUS_SE0); 316bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008018_GRBM_STATUS_SE1); 317bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008038_GRBM_STATUS_SE2); 318bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_00803C_GRBM_STATUS_SE3); 319bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_00D034_SDMA0_STATUS_REG); 320bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_00D834_SDMA1_STATUS_REG); 321bf215546Sopenharmony_ci if (sctx->gfx_level <= GFX8) { 322bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_000E50_SRBM_STATUS); 323bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_000E4C_SRBM_STATUS2); 324bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_000E54_SRBM_STATUS3); 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008680_CP_STAT); 327bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008674_CP_STALLED_STAT1); 328bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008678_CP_STALLED_STAT2); 329bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008670_CP_STALLED_STAT3); 330bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008210_CP_CPC_STATUS); 331bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008214_CP_CPC_BUSY_STAT); 332bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008218_CP_CPC_STALLED_STAT1); 333bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_00821C_CP_CPF_STATUS); 334bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008220_CP_CPF_BUSY_STAT); 335bf215546Sopenharmony_ci si_dump_mmapped_reg(sctx, f, R_008224_CP_CPF_STALLED_STAT1); 336bf215546Sopenharmony_ci fprintf(f, "\n"); 337bf215546Sopenharmony_ci} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_cistruct si_log_chunk_cs { 340bf215546Sopenharmony_ci struct si_context *ctx; 341bf215546Sopenharmony_ci struct si_saved_cs *cs; 342bf215546Sopenharmony_ci bool dump_bo_list; 343bf215546Sopenharmony_ci unsigned gfx_begin, gfx_end; 344bf215546Sopenharmony_ci}; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_cistatic void si_log_chunk_type_cs_destroy(void *data) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci struct si_log_chunk_cs *chunk = data; 349bf215546Sopenharmony_ci si_saved_cs_reference(&chunk->cs, NULL); 350bf215546Sopenharmony_ci free(chunk); 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_cistatic void si_parse_current_ib(FILE *f, struct radeon_cmdbuf *cs, unsigned begin, unsigned end, 354bf215546Sopenharmony_ci int *last_trace_id, unsigned trace_id_count, const char *name, 355bf215546Sopenharmony_ci enum amd_gfx_level gfx_level) 356bf215546Sopenharmony_ci{ 357bf215546Sopenharmony_ci unsigned orig_end = end; 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci assert(begin <= end); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci fprintf(f, "------------------ %s begin (dw = %u) ------------------\n", name, begin); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci for (unsigned prev_idx = 0; prev_idx < cs->num_prev; ++prev_idx) { 364bf215546Sopenharmony_ci struct radeon_cmdbuf_chunk *chunk = &cs->prev[prev_idx]; 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci if (begin < chunk->cdw) { 367bf215546Sopenharmony_ci ac_parse_ib_chunk(f, chunk->buf + begin, MIN2(end, chunk->cdw) - begin, last_trace_id, 368bf215546Sopenharmony_ci trace_id_count, gfx_level, NULL, NULL); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (end <= chunk->cdw) 372bf215546Sopenharmony_ci return; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci if (begin < chunk->cdw) 375bf215546Sopenharmony_ci fprintf(f, "\n---------- Next %s Chunk ----------\n\n", name); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci begin -= MIN2(begin, chunk->cdw); 378bf215546Sopenharmony_ci end -= chunk->cdw; 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci assert(end <= cs->current.cdw); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci ac_parse_ib_chunk(f, cs->current.buf + begin, end - begin, last_trace_id, trace_id_count, 384bf215546Sopenharmony_ci gfx_level, NULL, NULL); 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci fprintf(f, "------------------- %s end (dw = %u) -------------------\n\n", name, orig_end); 387bf215546Sopenharmony_ci} 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_civoid si_print_current_ib(struct si_context *sctx, FILE *f) 390bf215546Sopenharmony_ci{ 391bf215546Sopenharmony_ci si_parse_current_ib(f, &sctx->gfx_cs, 0, sctx->gfx_cs.prev_dw + sctx->gfx_cs.current.cdw, 392bf215546Sopenharmony_ci NULL, 0, "GFX", sctx->gfx_level); 393bf215546Sopenharmony_ci} 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_cistatic void si_log_chunk_type_cs_print(void *data, FILE *f) 396bf215546Sopenharmony_ci{ 397bf215546Sopenharmony_ci struct si_log_chunk_cs *chunk = data; 398bf215546Sopenharmony_ci struct si_context *ctx = chunk->ctx; 399bf215546Sopenharmony_ci struct si_saved_cs *scs = chunk->cs; 400bf215546Sopenharmony_ci int last_trace_id = -1; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci /* We are expecting that the ddebug pipe has already 403bf215546Sopenharmony_ci * waited for the context, so this buffer should be idle. 404bf215546Sopenharmony_ci * If the GPU is hung, there is no point in waiting for it. 405bf215546Sopenharmony_ci */ 406bf215546Sopenharmony_ci uint32_t *map = ctx->ws->buffer_map(ctx->ws, scs->trace_buf->buf, NULL, 407bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED | PIPE_MAP_READ); 408bf215546Sopenharmony_ci if (map) 409bf215546Sopenharmony_ci last_trace_id = map[0]; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci if (chunk->gfx_end != chunk->gfx_begin) { 412bf215546Sopenharmony_ci if (chunk->gfx_begin == 0) { 413bf215546Sopenharmony_ci if (ctx->cs_preamble_state) 414bf215546Sopenharmony_ci ac_parse_ib(f, ctx->cs_preamble_state->pm4, ctx->cs_preamble_state->ndw, NULL, 0, 415bf215546Sopenharmony_ci "IB2: Init config", ctx->gfx_level, NULL, NULL); 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci if (scs->flushed) { 419bf215546Sopenharmony_ci ac_parse_ib(f, scs->gfx.ib + chunk->gfx_begin, chunk->gfx_end - chunk->gfx_begin, 420bf215546Sopenharmony_ci &last_trace_id, map ? 1 : 0, "IB", ctx->gfx_level, NULL, NULL); 421bf215546Sopenharmony_ci } else { 422bf215546Sopenharmony_ci si_parse_current_ib(f, &ctx->gfx_cs, chunk->gfx_begin, chunk->gfx_end, &last_trace_id, 423bf215546Sopenharmony_ci map ? 1 : 0, "IB", ctx->gfx_level); 424bf215546Sopenharmony_ci } 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci if (chunk->dump_bo_list) { 428bf215546Sopenharmony_ci fprintf(f, "Flushing. Time: "); 429bf215546Sopenharmony_ci util_dump_ns(f, scs->time_flush); 430bf215546Sopenharmony_ci fprintf(f, "\n\n"); 431bf215546Sopenharmony_ci si_dump_bo_list(ctx, &scs->gfx, f); 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci} 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_cistatic const struct u_log_chunk_type si_log_chunk_type_cs = { 436bf215546Sopenharmony_ci .destroy = si_log_chunk_type_cs_destroy, 437bf215546Sopenharmony_ci .print = si_log_chunk_type_cs_print, 438bf215546Sopenharmony_ci}; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_cistatic void si_log_cs(struct si_context *ctx, struct u_log_context *log, bool dump_bo_list) 441bf215546Sopenharmony_ci{ 442bf215546Sopenharmony_ci assert(ctx->current_saved_cs); 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci struct si_saved_cs *scs = ctx->current_saved_cs; 445bf215546Sopenharmony_ci unsigned gfx_cur = ctx->gfx_cs.prev_dw + ctx->gfx_cs.current.cdw; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci if (!dump_bo_list && gfx_cur == scs->gfx_last_dw) 448bf215546Sopenharmony_ci return; 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci struct si_log_chunk_cs *chunk = calloc(1, sizeof(*chunk)); 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci chunk->ctx = ctx; 453bf215546Sopenharmony_ci si_saved_cs_reference(&chunk->cs, scs); 454bf215546Sopenharmony_ci chunk->dump_bo_list = dump_bo_list; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci chunk->gfx_begin = scs->gfx_last_dw; 457bf215546Sopenharmony_ci chunk->gfx_end = gfx_cur; 458bf215546Sopenharmony_ci scs->gfx_last_dw = gfx_cur; 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci u_log_chunk(log, &si_log_chunk_type_cs, chunk); 461bf215546Sopenharmony_ci} 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_civoid si_auto_log_cs(void *data, struct u_log_context *log) 464bf215546Sopenharmony_ci{ 465bf215546Sopenharmony_ci struct si_context *ctx = (struct si_context *)data; 466bf215546Sopenharmony_ci si_log_cs(ctx, log, false); 467bf215546Sopenharmony_ci} 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_civoid si_log_hw_flush(struct si_context *sctx) 470bf215546Sopenharmony_ci{ 471bf215546Sopenharmony_ci if (!sctx->log) 472bf215546Sopenharmony_ci return; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci si_log_cs(sctx, sctx->log, true); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci if (&sctx->b == sctx->screen->aux_context) { 477bf215546Sopenharmony_ci /* The aux context isn't captured by the ddebug wrapper, 478bf215546Sopenharmony_ci * so we dump it on a flush-by-flush basis here. 479bf215546Sopenharmony_ci */ 480bf215546Sopenharmony_ci FILE *f = dd_get_debug_file(false); 481bf215546Sopenharmony_ci if (!f) { 482bf215546Sopenharmony_ci fprintf(stderr, "radeonsi: error opening aux context dump file.\n"); 483bf215546Sopenharmony_ci } else { 484bf215546Sopenharmony_ci dd_write_header(f, &sctx->screen->b, 0); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci fprintf(f, "Aux context dump:\n\n"); 487bf215546Sopenharmony_ci u_log_new_page_print(sctx->log, f); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci fclose(f); 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci } 492bf215546Sopenharmony_ci} 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_cistatic const char *priority_to_string(unsigned priority) 495bf215546Sopenharmony_ci{ 496bf215546Sopenharmony_ci#define ITEM(x) if (priority == RADEON_PRIO_##x) return #x 497bf215546Sopenharmony_ci ITEM(FENCE_TRACE); 498bf215546Sopenharmony_ci ITEM(SO_FILLED_SIZE); 499bf215546Sopenharmony_ci ITEM(QUERY); 500bf215546Sopenharmony_ci ITEM(IB); 501bf215546Sopenharmony_ci ITEM(DRAW_INDIRECT); 502bf215546Sopenharmony_ci ITEM(INDEX_BUFFER); 503bf215546Sopenharmony_ci ITEM(CP_DMA); 504bf215546Sopenharmony_ci ITEM(BORDER_COLORS); 505bf215546Sopenharmony_ci ITEM(CONST_BUFFER); 506bf215546Sopenharmony_ci ITEM(DESCRIPTORS); 507bf215546Sopenharmony_ci ITEM(SAMPLER_BUFFER); 508bf215546Sopenharmony_ci ITEM(VERTEX_BUFFER); 509bf215546Sopenharmony_ci ITEM(SHADER_RW_BUFFER); 510bf215546Sopenharmony_ci ITEM(SAMPLER_TEXTURE); 511bf215546Sopenharmony_ci ITEM(SHADER_RW_IMAGE); 512bf215546Sopenharmony_ci ITEM(SAMPLER_TEXTURE_MSAA); 513bf215546Sopenharmony_ci ITEM(COLOR_BUFFER); 514bf215546Sopenharmony_ci ITEM(DEPTH_BUFFER); 515bf215546Sopenharmony_ci ITEM(COLOR_BUFFER_MSAA); 516bf215546Sopenharmony_ci ITEM(DEPTH_BUFFER_MSAA); 517bf215546Sopenharmony_ci ITEM(SEPARATE_META); 518bf215546Sopenharmony_ci ITEM(SHADER_BINARY); 519bf215546Sopenharmony_ci ITEM(SHADER_RINGS); 520bf215546Sopenharmony_ci ITEM(SCRATCH_BUFFER); 521bf215546Sopenharmony_ci#undef ITEM 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci return ""; 524bf215546Sopenharmony_ci} 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_cistatic int bo_list_compare_va(const struct radeon_bo_list_item *a, 527bf215546Sopenharmony_ci const struct radeon_bo_list_item *b) 528bf215546Sopenharmony_ci{ 529bf215546Sopenharmony_ci return a->vm_address < b->vm_address ? -1 : a->vm_address > b->vm_address ? 1 : 0; 530bf215546Sopenharmony_ci} 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_cistatic void si_dump_bo_list(struct si_context *sctx, const struct radeon_saved_cs *saved, FILE *f) 533bf215546Sopenharmony_ci{ 534bf215546Sopenharmony_ci unsigned i, j; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci if (!saved->bo_list) 537bf215546Sopenharmony_ci return; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci /* Sort the list according to VM adddresses first. */ 540bf215546Sopenharmony_ci qsort(saved->bo_list, saved->bo_count, sizeof(saved->bo_list[0]), (void *)bo_list_compare_va); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci fprintf(f, "Buffer list (in units of pages = 4kB):\n" COLOR_YELLOW 543bf215546Sopenharmony_ci " Size VM start page " 544bf215546Sopenharmony_ci "VM end page Usage" COLOR_RESET "\n"); 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci for (i = 0; i < saved->bo_count; i++) { 547bf215546Sopenharmony_ci /* Note: Buffer sizes are expected to be aligned to 4k by the winsys. */ 548bf215546Sopenharmony_ci const unsigned page_size = sctx->screen->info.gart_page_size; 549bf215546Sopenharmony_ci uint64_t va = saved->bo_list[i].vm_address; 550bf215546Sopenharmony_ci uint64_t size = saved->bo_list[i].bo_size; 551bf215546Sopenharmony_ci bool hit = false; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci /* If there's unused virtual memory between 2 buffers, print it. */ 554bf215546Sopenharmony_ci if (i) { 555bf215546Sopenharmony_ci uint64_t previous_va_end = 556bf215546Sopenharmony_ci saved->bo_list[i - 1].vm_address + saved->bo_list[i - 1].bo_size; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci if (va > previous_va_end) { 559bf215546Sopenharmony_ci fprintf(f, " %10" PRIu64 " -- hole --\n", (va - previous_va_end) / page_size); 560bf215546Sopenharmony_ci } 561bf215546Sopenharmony_ci } 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci /* Print the buffer. */ 564bf215546Sopenharmony_ci fprintf(f, " %10" PRIu64 " 0x%013" PRIX64 " 0x%013" PRIX64 " ", 565bf215546Sopenharmony_ci size / page_size, va / page_size, (va + size) / page_size); 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci /* Print the usage. */ 568bf215546Sopenharmony_ci for (j = 0; j < 32; j++) { 569bf215546Sopenharmony_ci if (!(saved->bo_list[i].priority_usage & (1u << j))) 570bf215546Sopenharmony_ci continue; 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci fprintf(f, "%s%s", !hit ? "" : ", ", priority_to_string(1u << j)); 573bf215546Sopenharmony_ci hit = true; 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci fprintf(f, "\n"); 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci fprintf(f, "\nNote: The holes represent memory not used by the IB.\n" 578bf215546Sopenharmony_ci " Other buffers can still be allocated there.\n\n"); 579bf215546Sopenharmony_ci} 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_cistatic void si_dump_framebuffer(struct si_context *sctx, struct u_log_context *log) 582bf215546Sopenharmony_ci{ 583bf215546Sopenharmony_ci struct pipe_framebuffer_state *state = &sctx->framebuffer.state; 584bf215546Sopenharmony_ci struct si_texture *tex; 585bf215546Sopenharmony_ci int i; 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci for (i = 0; i < state->nr_cbufs; i++) { 588bf215546Sopenharmony_ci if (!state->cbufs[i]) 589bf215546Sopenharmony_ci continue; 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci tex = (struct si_texture *)state->cbufs[i]->texture; 592bf215546Sopenharmony_ci u_log_printf(log, COLOR_YELLOW "Color buffer %i:" COLOR_RESET "\n", i); 593bf215546Sopenharmony_ci si_print_texture_info(sctx->screen, tex, log); 594bf215546Sopenharmony_ci u_log_printf(log, "\n"); 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci if (state->zsbuf) { 598bf215546Sopenharmony_ci tex = (struct si_texture *)state->zsbuf->texture; 599bf215546Sopenharmony_ci u_log_printf(log, COLOR_YELLOW "Depth-stencil buffer:" COLOR_RESET "\n"); 600bf215546Sopenharmony_ci si_print_texture_info(sctx->screen, tex, log); 601bf215546Sopenharmony_ci u_log_printf(log, "\n"); 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci} 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_citypedef unsigned (*slot_remap_func)(unsigned); 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_cistruct si_log_chunk_desc_list { 608bf215546Sopenharmony_ci /** Pointer to memory map of buffer where the list is uploader */ 609bf215546Sopenharmony_ci uint32_t *gpu_list; 610bf215546Sopenharmony_ci /** Reference of buffer where the list is uploaded, so that gpu_list 611bf215546Sopenharmony_ci * is kept live. */ 612bf215546Sopenharmony_ci struct si_resource *buf; 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_ci const char *shader_name; 615bf215546Sopenharmony_ci const char *elem_name; 616bf215546Sopenharmony_ci slot_remap_func slot_remap; 617bf215546Sopenharmony_ci enum amd_gfx_level gfx_level; 618bf215546Sopenharmony_ci unsigned element_dw_size; 619bf215546Sopenharmony_ci unsigned num_elements; 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci uint32_t list[0]; 622bf215546Sopenharmony_ci}; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_cistatic void si_log_chunk_desc_list_destroy(void *data) 625bf215546Sopenharmony_ci{ 626bf215546Sopenharmony_ci struct si_log_chunk_desc_list *chunk = data; 627bf215546Sopenharmony_ci si_resource_reference(&chunk->buf, NULL); 628bf215546Sopenharmony_ci FREE(chunk); 629bf215546Sopenharmony_ci} 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_cistatic void si_log_chunk_desc_list_print(void *data, FILE *f) 632bf215546Sopenharmony_ci{ 633bf215546Sopenharmony_ci struct si_log_chunk_desc_list *chunk = data; 634bf215546Sopenharmony_ci unsigned sq_img_rsrc_word0 = 635bf215546Sopenharmony_ci chunk->gfx_level >= GFX10 ? R_00A000_SQ_IMG_RSRC_WORD0 : R_008F10_SQ_IMG_RSRC_WORD0; 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci for (unsigned i = 0; i < chunk->num_elements; i++) { 638bf215546Sopenharmony_ci unsigned cpu_dw_offset = i * chunk->element_dw_size; 639bf215546Sopenharmony_ci unsigned gpu_dw_offset = chunk->slot_remap(i) * chunk->element_dw_size; 640bf215546Sopenharmony_ci const char *list_note = chunk->gpu_list ? "GPU list" : "CPU list"; 641bf215546Sopenharmony_ci uint32_t *cpu_list = chunk->list + cpu_dw_offset; 642bf215546Sopenharmony_ci uint32_t *gpu_list = chunk->gpu_list ? chunk->gpu_list + gpu_dw_offset : cpu_list; 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci fprintf(f, COLOR_GREEN "%s%s slot %u (%s):" COLOR_RESET "\n", chunk->shader_name, 645bf215546Sopenharmony_ci chunk->elem_name, i, list_note); 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci switch (chunk->element_dw_size) { 648bf215546Sopenharmony_ci case 4: 649bf215546Sopenharmony_ci for (unsigned j = 0; j < 4; j++) 650bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, gpu_list[j], 651bf215546Sopenharmony_ci 0xffffffff); 652bf215546Sopenharmony_ci break; 653bf215546Sopenharmony_ci case 8: 654bf215546Sopenharmony_ci for (unsigned j = 0; j < 8; j++) 655bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, sq_img_rsrc_word0 + j * 4, gpu_list[j], 0xffffffff); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN " Buffer:" COLOR_RESET "\n"); 658bf215546Sopenharmony_ci for (unsigned j = 0; j < 4; j++) 659bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, gpu_list[4 + j], 660bf215546Sopenharmony_ci 0xffffffff); 661bf215546Sopenharmony_ci break; 662bf215546Sopenharmony_ci case 16: 663bf215546Sopenharmony_ci for (unsigned j = 0; j < 8; j++) 664bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, sq_img_rsrc_word0 + j * 4, gpu_list[j], 0xffffffff); 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN " Buffer:" COLOR_RESET "\n"); 667bf215546Sopenharmony_ci for (unsigned j = 0; j < 4; j++) 668bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, gpu_list[4 + j], 669bf215546Sopenharmony_ci 0xffffffff); 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN " FMASK:" COLOR_RESET "\n"); 672bf215546Sopenharmony_ci for (unsigned j = 0; j < 8; j++) 673bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, sq_img_rsrc_word0 + j * 4, gpu_list[8 + j], 674bf215546Sopenharmony_ci 0xffffffff); 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN " Sampler state:" COLOR_RESET "\n"); 677bf215546Sopenharmony_ci for (unsigned j = 0; j < 4; j++) 678bf215546Sopenharmony_ci ac_dump_reg(f, chunk->gfx_level, R_008F30_SQ_IMG_SAMP_WORD0 + j * 4, gpu_list[12 + j], 679bf215546Sopenharmony_ci 0xffffffff); 680bf215546Sopenharmony_ci break; 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci if (memcmp(gpu_list, cpu_list, chunk->element_dw_size * 4) != 0) { 684bf215546Sopenharmony_ci fprintf(f, COLOR_RED "!!!!! This slot was corrupted in GPU memory !!!!!" COLOR_RESET "\n"); 685bf215546Sopenharmony_ci } 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci fprintf(f, "\n"); 688bf215546Sopenharmony_ci } 689bf215546Sopenharmony_ci} 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_cistatic const struct u_log_chunk_type si_log_chunk_type_descriptor_list = { 692bf215546Sopenharmony_ci .destroy = si_log_chunk_desc_list_destroy, 693bf215546Sopenharmony_ci .print = si_log_chunk_desc_list_print, 694bf215546Sopenharmony_ci}; 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_cistatic void si_dump_descriptor_list(struct si_screen *screen, struct si_descriptors *desc, 697bf215546Sopenharmony_ci const char *shader_name, const char *elem_name, 698bf215546Sopenharmony_ci unsigned element_dw_size, unsigned num_elements, 699bf215546Sopenharmony_ci slot_remap_func slot_remap, struct u_log_context *log) 700bf215546Sopenharmony_ci{ 701bf215546Sopenharmony_ci if (!desc->list) 702bf215546Sopenharmony_ci return; 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_ci /* In some cases, the caller doesn't know how many elements are really 705bf215546Sopenharmony_ci * uploaded. Reduce num_elements to fit in the range of active slots. */ 706bf215546Sopenharmony_ci unsigned active_range_dw_begin = desc->first_active_slot * desc->element_dw_size; 707bf215546Sopenharmony_ci unsigned active_range_dw_end = 708bf215546Sopenharmony_ci active_range_dw_begin + desc->num_active_slots * desc->element_dw_size; 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci while (num_elements > 0) { 711bf215546Sopenharmony_ci int i = slot_remap(num_elements - 1); 712bf215546Sopenharmony_ci unsigned dw_begin = i * element_dw_size; 713bf215546Sopenharmony_ci unsigned dw_end = dw_begin + element_dw_size; 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci if (dw_begin >= active_range_dw_begin && dw_end <= active_range_dw_end) 716bf215546Sopenharmony_ci break; 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci num_elements--; 719bf215546Sopenharmony_ci } 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci struct si_log_chunk_desc_list *chunk = 722bf215546Sopenharmony_ci CALLOC_VARIANT_LENGTH_STRUCT(si_log_chunk_desc_list, 4 * element_dw_size * num_elements); 723bf215546Sopenharmony_ci chunk->shader_name = shader_name; 724bf215546Sopenharmony_ci chunk->elem_name = elem_name; 725bf215546Sopenharmony_ci chunk->element_dw_size = element_dw_size; 726bf215546Sopenharmony_ci chunk->num_elements = num_elements; 727bf215546Sopenharmony_ci chunk->slot_remap = slot_remap; 728bf215546Sopenharmony_ci chunk->gfx_level = screen->info.gfx_level; 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci si_resource_reference(&chunk->buf, desc->buffer); 731bf215546Sopenharmony_ci chunk->gpu_list = desc->gpu_list; 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci for (unsigned i = 0; i < num_elements; ++i) { 734bf215546Sopenharmony_ci memcpy(&chunk->list[i * element_dw_size], &desc->list[slot_remap(i) * element_dw_size], 735bf215546Sopenharmony_ci 4 * element_dw_size); 736bf215546Sopenharmony_ci } 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci u_log_chunk(log, &si_log_chunk_type_descriptor_list, chunk); 739bf215546Sopenharmony_ci} 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_cistatic unsigned si_identity(unsigned slot) 742bf215546Sopenharmony_ci{ 743bf215546Sopenharmony_ci return slot; 744bf215546Sopenharmony_ci} 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_cistatic void si_dump_descriptors(struct si_context *sctx, gl_shader_stage stage, 747bf215546Sopenharmony_ci const struct si_shader_info *info, struct u_log_context *log) 748bf215546Sopenharmony_ci{ 749bf215546Sopenharmony_ci enum pipe_shader_type processor = pipe_shader_type_from_mesa(stage); 750bf215546Sopenharmony_ci struct si_descriptors *descs = 751bf215546Sopenharmony_ci &sctx->descriptors[SI_DESCS_FIRST_SHADER + processor * SI_NUM_SHADER_DESCS]; 752bf215546Sopenharmony_ci static const char *shader_name[] = {"VS", "PS", "GS", "TCS", "TES", "CS"}; 753bf215546Sopenharmony_ci const char *name = shader_name[processor]; 754bf215546Sopenharmony_ci unsigned enabled_constbuf, enabled_shaderbuf, enabled_samplers; 755bf215546Sopenharmony_ci unsigned enabled_images; 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci if (info) { 758bf215546Sopenharmony_ci enabled_constbuf = u_bit_consecutive(0, info->base.num_ubos); 759bf215546Sopenharmony_ci enabled_shaderbuf = u_bit_consecutive(0, info->base.num_ssbos); 760bf215546Sopenharmony_ci enabled_samplers = info->base.textures_used[0]; 761bf215546Sopenharmony_ci enabled_images = u_bit_consecutive(0, info->base.num_images); 762bf215546Sopenharmony_ci } else { 763bf215546Sopenharmony_ci enabled_constbuf = 764bf215546Sopenharmony_ci sctx->const_and_shader_buffers[processor].enabled_mask >> SI_NUM_SHADER_BUFFERS; 765bf215546Sopenharmony_ci enabled_shaderbuf = 0; 766bf215546Sopenharmony_ci for (int i = 0; i < SI_NUM_SHADER_BUFFERS; i++) { 767bf215546Sopenharmony_ci enabled_shaderbuf |= 768bf215546Sopenharmony_ci (sctx->const_and_shader_buffers[processor].enabled_mask & 769bf215546Sopenharmony_ci 1llu << (SI_NUM_SHADER_BUFFERS - i - 1)) << i; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci enabled_samplers = sctx->samplers[processor].enabled_mask; 772bf215546Sopenharmony_ci enabled_images = sctx->images[processor].enabled_mask; 773bf215546Sopenharmony_ci } 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci if (stage == MESA_SHADER_VERTEX && sctx->vb_descriptors_buffer && 776bf215546Sopenharmony_ci sctx->vb_descriptors_gpu_list) { 777bf215546Sopenharmony_ci assert(info); /* only CS may not have an info struct */ 778bf215546Sopenharmony_ci struct si_descriptors desc = {}; 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci desc.buffer = sctx->vb_descriptors_buffer; 781bf215546Sopenharmony_ci desc.list = sctx->vb_descriptors_gpu_list; 782bf215546Sopenharmony_ci desc.gpu_list = sctx->vb_descriptors_gpu_list; 783bf215546Sopenharmony_ci desc.element_dw_size = 4; 784bf215546Sopenharmony_ci desc.num_active_slots = sctx->vertex_elements->vb_desc_list_alloc_size / 16; 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &desc, name, " - Vertex buffer", 4, info->num_inputs, 787bf215546Sopenharmony_ci si_identity, log); 788bf215546Sopenharmony_ci } 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &descs[SI_SHADER_DESCS_CONST_AND_SHADER_BUFFERS], name, 791bf215546Sopenharmony_ci " - Constant buffer", 4, util_last_bit(enabled_constbuf), 792bf215546Sopenharmony_ci si_get_constbuf_slot, log); 793bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &descs[SI_SHADER_DESCS_CONST_AND_SHADER_BUFFERS], name, 794bf215546Sopenharmony_ci " - Shader buffer", 4, util_last_bit(enabled_shaderbuf), 795bf215546Sopenharmony_ci si_get_shaderbuf_slot, log); 796bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &descs[SI_SHADER_DESCS_SAMPLERS_AND_IMAGES], name, 797bf215546Sopenharmony_ci " - Sampler", 16, util_last_bit(enabled_samplers), si_get_sampler_slot, 798bf215546Sopenharmony_ci log); 799bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &descs[SI_SHADER_DESCS_SAMPLERS_AND_IMAGES], name, 800bf215546Sopenharmony_ci " - Image", 8, util_last_bit(enabled_images), si_get_image_slot, log); 801bf215546Sopenharmony_ci} 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_cistatic void si_dump_gfx_descriptors(struct si_context *sctx, 804bf215546Sopenharmony_ci const struct si_shader_ctx_state *state, 805bf215546Sopenharmony_ci struct u_log_context *log) 806bf215546Sopenharmony_ci{ 807bf215546Sopenharmony_ci if (!state->cso || !state->current) 808bf215546Sopenharmony_ci return; 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci si_dump_descriptors(sctx, state->cso->stage, &state->cso->info, log); 811bf215546Sopenharmony_ci} 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_cistatic void si_dump_compute_descriptors(struct si_context *sctx, struct u_log_context *log) 814bf215546Sopenharmony_ci{ 815bf215546Sopenharmony_ci if (!sctx->cs_shader_state.program) 816bf215546Sopenharmony_ci return; 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci si_dump_descriptors(sctx, MESA_SHADER_COMPUTE, NULL, log); 819bf215546Sopenharmony_ci} 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_cistruct si_shader_inst { 822bf215546Sopenharmony_ci const char *text; /* start of disassembly for this instruction */ 823bf215546Sopenharmony_ci unsigned textlen; 824bf215546Sopenharmony_ci unsigned size; /* instruction size = 4 or 8 */ 825bf215546Sopenharmony_ci uint64_t addr; /* instruction address */ 826bf215546Sopenharmony_ci}; 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci/** 829bf215546Sopenharmony_ci * Open the given \p binary as \p rtld_binary and split the contained 830bf215546Sopenharmony_ci * disassembly string into instructions and add them to the array 831bf215546Sopenharmony_ci * pointed to by \p instructions, which must be sufficiently large. 832bf215546Sopenharmony_ci * 833bf215546Sopenharmony_ci * Labels are considered to be part of the following instruction. 834bf215546Sopenharmony_ci * 835bf215546Sopenharmony_ci * The caller must keep \p rtld_binary alive as long as \p instructions are 836bf215546Sopenharmony_ci * used and then close it afterwards. 837bf215546Sopenharmony_ci */ 838bf215546Sopenharmony_cistatic void si_add_split_disasm(struct si_screen *screen, struct ac_rtld_binary *rtld_binary, 839bf215546Sopenharmony_ci struct si_shader_binary *binary, uint64_t *addr, unsigned *num, 840bf215546Sopenharmony_ci struct si_shader_inst *instructions, 841bf215546Sopenharmony_ci gl_shader_stage stage, unsigned wave_size) 842bf215546Sopenharmony_ci{ 843bf215546Sopenharmony_ci if (!ac_rtld_open(rtld_binary, (struct ac_rtld_open_info){ 844bf215546Sopenharmony_ci .info = &screen->info, 845bf215546Sopenharmony_ci .shader_type = stage, 846bf215546Sopenharmony_ci .wave_size = wave_size, 847bf215546Sopenharmony_ci .num_parts = 1, 848bf215546Sopenharmony_ci .elf_ptrs = &binary->elf_buffer, 849bf215546Sopenharmony_ci .elf_sizes = &binary->elf_size})) 850bf215546Sopenharmony_ci return; 851bf215546Sopenharmony_ci 852bf215546Sopenharmony_ci const char *disasm; 853bf215546Sopenharmony_ci size_t nbytes; 854bf215546Sopenharmony_ci if (!ac_rtld_get_section_by_name(rtld_binary, ".AMDGPU.disasm", &disasm, &nbytes)) 855bf215546Sopenharmony_ci return; 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci const char *end = disasm + nbytes; 858bf215546Sopenharmony_ci while (disasm < end) { 859bf215546Sopenharmony_ci const char *semicolon = memchr(disasm, ';', end - disasm); 860bf215546Sopenharmony_ci if (!semicolon) 861bf215546Sopenharmony_ci break; 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci struct si_shader_inst *inst = &instructions[(*num)++]; 864bf215546Sopenharmony_ci const char *inst_end = memchr(semicolon + 1, '\n', end - semicolon - 1); 865bf215546Sopenharmony_ci if (!inst_end) 866bf215546Sopenharmony_ci inst_end = end; 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci inst->text = disasm; 869bf215546Sopenharmony_ci inst->textlen = inst_end - disasm; 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci inst->addr = *addr; 872bf215546Sopenharmony_ci /* More than 16 chars after ";" means the instruction is 8 bytes long. */ 873bf215546Sopenharmony_ci inst->size = inst_end - semicolon > 16 ? 8 : 4; 874bf215546Sopenharmony_ci *addr += inst->size; 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci if (inst_end == end) 877bf215546Sopenharmony_ci break; 878bf215546Sopenharmony_ci disasm = inst_end + 1; 879bf215546Sopenharmony_ci } 880bf215546Sopenharmony_ci} 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci/* If the shader is being executed, print its asm instructions, and annotate 883bf215546Sopenharmony_ci * those that are being executed right now with information about waves that 884bf215546Sopenharmony_ci * execute them. This is most useful during a GPU hang. 885bf215546Sopenharmony_ci */ 886bf215546Sopenharmony_cistatic void si_print_annotated_shader(struct si_shader *shader, struct ac_wave_info *waves, 887bf215546Sopenharmony_ci unsigned num_waves, FILE *f) 888bf215546Sopenharmony_ci{ 889bf215546Sopenharmony_ci if (!shader) 890bf215546Sopenharmony_ci return; 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci struct si_screen *screen = shader->selector->screen; 893bf215546Sopenharmony_ci gl_shader_stage stage = shader->selector->stage; 894bf215546Sopenharmony_ci uint64_t start_addr = shader->bo->gpu_address; 895bf215546Sopenharmony_ci uint64_t end_addr = start_addr + shader->bo->b.b.width0; 896bf215546Sopenharmony_ci unsigned i; 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_ci /* See if any wave executes the shader. */ 899bf215546Sopenharmony_ci for (i = 0; i < num_waves; i++) { 900bf215546Sopenharmony_ci if (start_addr <= waves[i].pc && waves[i].pc <= end_addr) 901bf215546Sopenharmony_ci break; 902bf215546Sopenharmony_ci } 903bf215546Sopenharmony_ci if (i == num_waves) 904bf215546Sopenharmony_ci return; /* the shader is not being executed */ 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci /* Remember the first found wave. The waves are sorted according to PC. */ 907bf215546Sopenharmony_ci waves = &waves[i]; 908bf215546Sopenharmony_ci num_waves -= i; 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci /* Get the list of instructions. 911bf215546Sopenharmony_ci * Buffer size / 4 is the upper bound of the instruction count. 912bf215546Sopenharmony_ci */ 913bf215546Sopenharmony_ci unsigned num_inst = 0; 914bf215546Sopenharmony_ci uint64_t inst_addr = start_addr; 915bf215546Sopenharmony_ci struct ac_rtld_binary rtld_binaries[5] = {}; 916bf215546Sopenharmony_ci struct si_shader_inst *instructions = 917bf215546Sopenharmony_ci calloc(shader->bo->b.b.width0 / 4, sizeof(struct si_shader_inst)); 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_ci if (shader->prolog) { 920bf215546Sopenharmony_ci si_add_split_disasm(screen, &rtld_binaries[0], &shader->prolog->binary, &inst_addr, &num_inst, 921bf215546Sopenharmony_ci instructions, stage, shader->wave_size); 922bf215546Sopenharmony_ci } 923bf215546Sopenharmony_ci if (shader->previous_stage) { 924bf215546Sopenharmony_ci si_add_split_disasm(screen, &rtld_binaries[1], &shader->previous_stage->binary, &inst_addr, 925bf215546Sopenharmony_ci &num_inst, instructions, stage, shader->wave_size); 926bf215546Sopenharmony_ci } 927bf215546Sopenharmony_ci si_add_split_disasm(screen, &rtld_binaries[3], &shader->binary, &inst_addr, &num_inst, 928bf215546Sopenharmony_ci instructions, stage, shader->wave_size); 929bf215546Sopenharmony_ci if (shader->epilog) { 930bf215546Sopenharmony_ci si_add_split_disasm(screen, &rtld_binaries[4], &shader->epilog->binary, &inst_addr, &num_inst, 931bf215546Sopenharmony_ci instructions, stage, shader->wave_size); 932bf215546Sopenharmony_ci } 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n", 935bf215546Sopenharmony_ci si_get_shader_name(shader)); 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci /* Print instructions with annotations. */ 938bf215546Sopenharmony_ci for (i = 0; i < num_inst; i++) { 939bf215546Sopenharmony_ci struct si_shader_inst *inst = &instructions[i]; 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci fprintf(f, "%.*s [PC=0x%" PRIx64 ", size=%u]\n", inst->textlen, inst->text, inst->addr, 942bf215546Sopenharmony_ci inst->size); 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci /* Print which waves execute the instruction right now. */ 945bf215546Sopenharmony_ci while (num_waves && inst->addr == waves->pc) { 946bf215546Sopenharmony_ci fprintf(f, 947bf215546Sopenharmony_ci " " COLOR_GREEN "^ SE%u SH%u CU%u " 948bf215546Sopenharmony_ci "SIMD%u WAVE%u EXEC=%016" PRIx64 " ", 949bf215546Sopenharmony_ci waves->se, waves->sh, waves->cu, waves->simd, waves->wave, waves->exec); 950bf215546Sopenharmony_ci 951bf215546Sopenharmony_ci if (inst->size == 4) { 952bf215546Sopenharmony_ci fprintf(f, "INST32=%08X" COLOR_RESET "\n", waves->inst_dw0); 953bf215546Sopenharmony_ci } else { 954bf215546Sopenharmony_ci fprintf(f, "INST64=%08X %08X" COLOR_RESET "\n", waves->inst_dw0, waves->inst_dw1); 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci 957bf215546Sopenharmony_ci waves->matched = true; 958bf215546Sopenharmony_ci waves = &waves[1]; 959bf215546Sopenharmony_ci num_waves--; 960bf215546Sopenharmony_ci } 961bf215546Sopenharmony_ci } 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci fprintf(f, "\n\n"); 964bf215546Sopenharmony_ci free(instructions); 965bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(rtld_binaries); ++i) 966bf215546Sopenharmony_ci ac_rtld_close(&rtld_binaries[i]); 967bf215546Sopenharmony_ci} 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_cistatic void si_dump_annotated_shaders(struct si_context *sctx, FILE *f) 970bf215546Sopenharmony_ci{ 971bf215546Sopenharmony_ci struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP]; 972bf215546Sopenharmony_ci unsigned num_waves = ac_get_wave_info(sctx->gfx_level, waves); 973bf215546Sopenharmony_ci 974bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN "The number of active waves = %u" COLOR_RESET "\n\n", num_waves); 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_ci si_print_annotated_shader(sctx->shader.vs.current, waves, num_waves, f); 977bf215546Sopenharmony_ci si_print_annotated_shader(sctx->shader.tcs.current, waves, num_waves, f); 978bf215546Sopenharmony_ci si_print_annotated_shader(sctx->shader.tes.current, waves, num_waves, f); 979bf215546Sopenharmony_ci si_print_annotated_shader(sctx->shader.gs.current, waves, num_waves, f); 980bf215546Sopenharmony_ci si_print_annotated_shader(sctx->shader.ps.current, waves, num_waves, f); 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci /* Print waves executing shaders that are not currently bound. */ 983bf215546Sopenharmony_ci unsigned i; 984bf215546Sopenharmony_ci bool found = false; 985bf215546Sopenharmony_ci for (i = 0; i < num_waves; i++) { 986bf215546Sopenharmony_ci if (waves[i].matched) 987bf215546Sopenharmony_ci continue; 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci if (!found) { 990bf215546Sopenharmony_ci fprintf(f, COLOR_CYAN "Waves not executing currently-bound shaders:" COLOR_RESET "\n"); 991bf215546Sopenharmony_ci found = true; 992bf215546Sopenharmony_ci } 993bf215546Sopenharmony_ci fprintf(f, 994bf215546Sopenharmony_ci " SE%u SH%u CU%u SIMD%u WAVE%u EXEC=%016" PRIx64 " INST=%08X %08X PC=%" PRIx64 995bf215546Sopenharmony_ci "\n", 996bf215546Sopenharmony_ci waves[i].se, waves[i].sh, waves[i].cu, waves[i].simd, waves[i].wave, waves[i].exec, 997bf215546Sopenharmony_ci waves[i].inst_dw0, waves[i].inst_dw1, waves[i].pc); 998bf215546Sopenharmony_ci } 999bf215546Sopenharmony_ci if (found) 1000bf215546Sopenharmony_ci fprintf(f, "\n\n"); 1001bf215546Sopenharmony_ci} 1002bf215546Sopenharmony_ci 1003bf215546Sopenharmony_cistatic void si_dump_command(const char *title, const char *command, FILE *f) 1004bf215546Sopenharmony_ci{ 1005bf215546Sopenharmony_ci char line[2000]; 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci FILE *p = popen(command, "r"); 1008bf215546Sopenharmony_ci if (!p) 1009bf215546Sopenharmony_ci return; 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci fprintf(f, COLOR_YELLOW "%s: " COLOR_RESET "\n", title); 1012bf215546Sopenharmony_ci while (fgets(line, sizeof(line), p)) 1013bf215546Sopenharmony_ci fputs(line, f); 1014bf215546Sopenharmony_ci fprintf(f, "\n\n"); 1015bf215546Sopenharmony_ci pclose(p); 1016bf215546Sopenharmony_ci} 1017bf215546Sopenharmony_ci 1018bf215546Sopenharmony_cistatic void si_dump_debug_state(struct pipe_context *ctx, FILE *f, unsigned flags) 1019bf215546Sopenharmony_ci{ 1020bf215546Sopenharmony_ci struct si_context *sctx = (struct si_context *)ctx; 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci if (sctx->log) 1023bf215546Sopenharmony_ci u_log_flush(sctx->log); 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci if (flags & PIPE_DUMP_DEVICE_STATUS_REGISTERS) { 1026bf215546Sopenharmony_ci si_dump_debug_registers(sctx, f); 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci si_dump_annotated_shaders(sctx, f); 1029bf215546Sopenharmony_ci si_dump_command("Active waves (raw data)", "umr -O halt_waves -wa | column -t", f); 1030bf215546Sopenharmony_ci si_dump_command("Wave information", "umr -O halt_waves,bits -wa", f); 1031bf215546Sopenharmony_ci } 1032bf215546Sopenharmony_ci} 1033bf215546Sopenharmony_ci 1034bf215546Sopenharmony_civoid si_log_draw_state(struct si_context *sctx, struct u_log_context *log) 1035bf215546Sopenharmony_ci{ 1036bf215546Sopenharmony_ci if (!log) 1037bf215546Sopenharmony_ci return; 1038bf215546Sopenharmony_ci 1039bf215546Sopenharmony_ci si_dump_framebuffer(sctx, log); 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci si_dump_gfx_shader(sctx, &sctx->shader.vs, log); 1042bf215546Sopenharmony_ci si_dump_gfx_shader(sctx, &sctx->shader.tcs, log); 1043bf215546Sopenharmony_ci si_dump_gfx_shader(sctx, &sctx->shader.tes, log); 1044bf215546Sopenharmony_ci si_dump_gfx_shader(sctx, &sctx->shader.gs, log); 1045bf215546Sopenharmony_ci si_dump_gfx_shader(sctx, &sctx->shader.ps, log); 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci si_dump_descriptor_list(sctx->screen, &sctx->descriptors[SI_DESCS_INTERNAL], "", "RW buffers", 1048bf215546Sopenharmony_ci 4, sctx->descriptors[SI_DESCS_INTERNAL].num_active_slots, si_identity, 1049bf215546Sopenharmony_ci log); 1050bf215546Sopenharmony_ci si_dump_gfx_descriptors(sctx, &sctx->shader.vs, log); 1051bf215546Sopenharmony_ci si_dump_gfx_descriptors(sctx, &sctx->shader.tcs, log); 1052bf215546Sopenharmony_ci si_dump_gfx_descriptors(sctx, &sctx->shader.tes, log); 1053bf215546Sopenharmony_ci si_dump_gfx_descriptors(sctx, &sctx->shader.gs, log); 1054bf215546Sopenharmony_ci si_dump_gfx_descriptors(sctx, &sctx->shader.ps, log); 1055bf215546Sopenharmony_ci} 1056bf215546Sopenharmony_ci 1057bf215546Sopenharmony_civoid si_log_compute_state(struct si_context *sctx, struct u_log_context *log) 1058bf215546Sopenharmony_ci{ 1059bf215546Sopenharmony_ci if (!log) 1060bf215546Sopenharmony_ci return; 1061bf215546Sopenharmony_ci 1062bf215546Sopenharmony_ci si_dump_compute_shader(sctx, log); 1063bf215546Sopenharmony_ci si_dump_compute_descriptors(sctx, log); 1064bf215546Sopenharmony_ci} 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_civoid si_check_vm_faults(struct si_context *sctx, struct radeon_saved_cs *saved, enum amd_ip_type ring) 1067bf215546Sopenharmony_ci{ 1068bf215546Sopenharmony_ci struct pipe_screen *screen = sctx->b.screen; 1069bf215546Sopenharmony_ci FILE *f; 1070bf215546Sopenharmony_ci uint64_t addr; 1071bf215546Sopenharmony_ci char cmd_line[4096]; 1072bf215546Sopenharmony_ci 1073bf215546Sopenharmony_ci if (!ac_vm_fault_occured(sctx->gfx_level, &sctx->dmesg_timestamp, &addr)) 1074bf215546Sopenharmony_ci return; 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci f = dd_get_debug_file(false); 1077bf215546Sopenharmony_ci if (!f) 1078bf215546Sopenharmony_ci return; 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci fprintf(f, "VM fault report.\n\n"); 1081bf215546Sopenharmony_ci if (os_get_command_line(cmd_line, sizeof(cmd_line))) 1082bf215546Sopenharmony_ci fprintf(f, "Command: %s\n", cmd_line); 1083bf215546Sopenharmony_ci fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen)); 1084bf215546Sopenharmony_ci fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen)); 1085bf215546Sopenharmony_ci fprintf(f, "Device name: %s\n\n", screen->get_name(screen)); 1086bf215546Sopenharmony_ci fprintf(f, "Failing VM page: 0x%08" PRIx64 "\n\n", addr); 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_ci if (sctx->apitrace_call_number) 1089bf215546Sopenharmony_ci fprintf(f, "Last apitrace call: %u\n\n", sctx->apitrace_call_number); 1090bf215546Sopenharmony_ci 1091bf215546Sopenharmony_ci switch (ring) { 1092bf215546Sopenharmony_ci case AMD_IP_GFX: { 1093bf215546Sopenharmony_ci struct u_log_context log; 1094bf215546Sopenharmony_ci u_log_context_init(&log); 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci si_log_draw_state(sctx, &log); 1097bf215546Sopenharmony_ci si_log_compute_state(sctx, &log); 1098bf215546Sopenharmony_ci si_log_cs(sctx, &log, true); 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci u_log_new_page_print(&log, f); 1101bf215546Sopenharmony_ci u_log_context_destroy(&log); 1102bf215546Sopenharmony_ci break; 1103bf215546Sopenharmony_ci } 1104bf215546Sopenharmony_ci 1105bf215546Sopenharmony_ci default: 1106bf215546Sopenharmony_ci break; 1107bf215546Sopenharmony_ci } 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci fclose(f); 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci fprintf(stderr, "Detected a VM fault, exiting...\n"); 1112bf215546Sopenharmony_ci exit(0); 1113bf215546Sopenharmony_ci} 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_civoid si_init_debug_functions(struct si_context *sctx) 1116bf215546Sopenharmony_ci{ 1117bf215546Sopenharmony_ci sctx->b.dump_debug_state = si_dump_debug_state; 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_ci /* Set the initial dmesg timestamp for this context, so that 1120bf215546Sopenharmony_ci * only new messages will be checked for VM faults. 1121bf215546Sopenharmony_ci */ 1122bf215546Sopenharmony_ci if (sctx->screen->debug_flags & DBG(CHECK_VM)) 1123bf215546Sopenharmony_ci ac_vm_fault_occured(sctx->gfx_level, &sctx->dmesg_timestamp, NULL); 1124bf215546Sopenharmony_ci} 1125