2017-08-30 15:12:20 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2016 Red Hat.
|
|
|
|
|
* Copyright © 2016 Bas Nieuwenhuizen
|
|
|
|
|
*
|
|
|
|
|
* based in part on anv driver which is:
|
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
|
*
|
2024-04-05 16:28:39 +02:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-08-30 15:12:20 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2020-12-03 02:15:50 -08:00
|
|
|
#ifndef _WIN32
|
2017-09-14 11:25:24 +02:00
|
|
|
#include <sys/utsname.h>
|
2020-12-03 02:15:50 -08:00
|
|
|
#endif
|
2020-10-19 17:56:14 +02:00
|
|
|
#include <sys/stat.h>
|
2017-08-30 15:12:20 +02:00
|
|
|
|
2018-04-18 18:53:44 +02:00
|
|
|
#include "util/mesa-sha1.h"
|
2022-04-09 21:53:03 +08:00
|
|
|
#include "util/os_time.h"
|
2017-08-31 11:44:00 +02:00
|
|
|
#include "ac_debug.h"
|
2024-05-16 17:50:57 +02:00
|
|
|
#include "ac_descriptors.h"
|
2024-04-01 15:52:30 +02:00
|
|
|
#include "radv_buffer.h"
|
2017-08-30 15:12:20 +02:00
|
|
|
#include "radv_debug.h"
|
2024-04-04 14:29:07 +02:00
|
|
|
#include "radv_descriptor_set.h"
|
|
|
|
|
#include "radv_entrypoints.h"
|
|
|
|
|
#include "radv_pipeline_graphics.h"
|
2024-04-02 08:45:36 +02:00
|
|
|
#include "radv_pipeline_rt.h"
|
2017-09-01 11:41:18 +02:00
|
|
|
#include "radv_shader.h"
|
2017-09-06 09:47:21 +02:00
|
|
|
#include "sid.h"
|
2024-08-27 10:17:30 -05:00
|
|
|
#include "spirv/nir_spirv.h"
|
2017-08-30 15:12:20 +02:00
|
|
|
|
2024-04-20 11:28:54 +02:00
|
|
|
#define TMA_BO_SIZE 4096
|
2017-09-13 11:13:03 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
#define COLOR_RESET "\033[0m"
|
|
|
|
|
#define COLOR_RED "\033[31m"
|
|
|
|
|
#define COLOR_GREEN "\033[1;32m"
|
|
|
|
|
#define COLOR_YELLOW "\033[1;33m"
|
|
|
|
|
#define COLOR_CYAN "\033[1;36m"
|
|
|
|
|
|
2020-10-19 17:56:14 +02:00
|
|
|
#define RADV_DUMP_DIR "radv_dumps"
|
|
|
|
|
|
2017-08-30 15:12:20 +02:00
|
|
|
bool
|
|
|
|
|
radv_init_trace(struct radv_device *device)
|
|
|
|
|
{
|
|
|
|
|
struct radeon_winsys *ws = device->ws;
|
2021-02-09 11:51:38 +01:00
|
|
|
VkResult result;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-03-25 14:54:08 +01:00
|
|
|
result = radv_bo_create(
|
2024-04-20 11:28:54 +02:00
|
|
|
device, NULL, sizeof(struct radv_trace_data), 8, RADEON_DOMAIN_VRAM,
|
2022-06-22 09:38:24 +02:00
|
|
|
RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_ZERO_VRAM | RADEON_FLAG_VA_UNCACHED,
|
2024-03-25 15:16:27 +01:00
|
|
|
RADV_BO_PRIORITY_UPLOAD_BUFFER, 0, true, &device->trace_bo);
|
2021-04-28 02:10:57 +02:00
|
|
|
if (result != VK_SUCCESS)
|
2017-08-30 15:12:20 +02:00
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-02-09 11:51:38 +01:00
|
|
|
result = ws->buffer_make_resident(ws, device->trace_bo, true);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-20 11:28:54 +02:00
|
|
|
device->trace_data = radv_buffer_map(ws, device->trace_bo);
|
|
|
|
|
if (!device->trace_data)
|
2017-08-30 15:12:20 +02:00
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-08-30 15:12:20 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 11:51:38 +01:00
|
|
|
void
|
|
|
|
|
radv_finish_trace(struct radv_device *device)
|
|
|
|
|
{
|
|
|
|
|
struct radeon_winsys *ws = device->ws;
|
|
|
|
|
|
|
|
|
|
if (unlikely(device->trace_bo)) {
|
|
|
|
|
ws->buffer_make_resident(ws, device->trace_bo, false);
|
2023-01-16 17:04:47 +01:00
|
|
|
radv_bo_destroy(device, NULL, device->trace_bo);
|
2021-02-09 11:51:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 09:44:45 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_trace(const struct radv_device *device, struct radeon_cmdbuf *cs, FILE *f)
|
2017-08-30 15:12:20 +02:00
|
|
|
{
|
2024-04-20 11:28:54 +02:00
|
|
|
fprintf(f, "Trace ID: %x\n", device->trace_data->primary_id);
|
|
|
|
|
device->ws->cs_dump(cs, f, (const int *)&device->trace_data->primary_id, 2, RADV_CS_DUMP_TYPE_IBS);
|
2017-08-30 15:12:20 +02:00
|
|
|
}
|
2017-08-30 15:12:21 +02:00
|
|
|
|
2017-09-06 09:47:21 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_mmapped_reg(const struct radv_device *device, FILE *f, unsigned offset)
|
2017-09-06 09:47:21 +02:00
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2017-09-06 09:47:21 +02:00
|
|
|
struct radeon_winsys *ws = device->ws;
|
|
|
|
|
uint32_t value;
|
|
|
|
|
|
|
|
|
|
if (ws->read_registers(ws, offset, 1, &value))
|
2024-03-28 14:42:10 +01:00
|
|
|
ac_dump_reg(f, pdev->info.gfx_level, pdev->info.family, offset, value, ~0);
|
2017-09-06 09:47:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_debug_registers(const struct radv_device *device, FILE *f)
|
2017-09-06 09:47:21 +02:00
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
const struct radeon_info *gpu_info = &pdev->info;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-06 09:47:21 +02:00
|
|
|
fprintf(f, "Memory-mapped registers:\n");
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008010_GRBM_STATUS);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-06 09:47:21 +02:00
|
|
|
radv_dump_mmapped_reg(device, f, R_008008_GRBM_STATUS2);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008014_GRBM_STATUS_SE0);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008018_GRBM_STATUS_SE1);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008038_GRBM_STATUS_SE2);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_00803C_GRBM_STATUS_SE3);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_00D034_SDMA0_STATUS_REG);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_00D834_SDMA1_STATUS_REG);
|
2024-03-28 13:44:11 +01:00
|
|
|
if (gpu_info->gfx_level <= GFX8) {
|
2017-09-06 09:47:21 +02:00
|
|
|
radv_dump_mmapped_reg(device, f, R_000E50_SRBM_STATUS);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_000E4C_SRBM_STATUS2);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_000E54_SRBM_STATUS3);
|
|
|
|
|
}
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008680_CP_STAT);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008674_CP_STALLED_STAT1);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008678_CP_STALLED_STAT2);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008670_CP_STALLED_STAT3);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008210_CP_CPC_STATUS);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008214_CP_CPC_BUSY_STAT);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008218_CP_CPC_STALLED_STAT1);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_00821C_CP_CPF_STATUS);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008220_CP_CPF_BUSY_STAT);
|
|
|
|
|
radv_dump_mmapped_reg(device, f, R_008224_CP_CPF_STALLED_STAT1);
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-11 16:13:05 +02:00
|
|
|
static void
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_buffer_descriptor(enum amd_gfx_level gfx_level, enum radeon_family family, const uint32_t *desc, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
2024-04-15 19:10:42 +02:00
|
|
|
fprintf(f, COLOR_CYAN "Buffer:" COLOR_RESET "\n");
|
2017-09-11 16:13:05 +02:00
|
|
|
for (unsigned j = 0; j < 4; j++)
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(f, gfx_level, family, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, desc[j], 0xffffffff);
|
2017-09-11 16:13:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_image_descriptor(enum amd_gfx_level gfx_level, enum radeon_family family, const uint32_t *desc, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
2022-05-12 02:50:17 -04:00
|
|
|
unsigned sq_img_rsrc_word0 = gfx_level >= GFX10 ? R_00A000_SQ_IMG_RSRC_WORD0 : R_008F10_SQ_IMG_RSRC_WORD0;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-15 19:10:42 +02:00
|
|
|
fprintf(f, COLOR_CYAN "Image:" COLOR_RESET "\n");
|
2017-09-11 16:13:05 +02:00
|
|
|
for (unsigned j = 0; j < 8; j++)
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(f, gfx_level, family, sq_img_rsrc_word0 + j * 4, desc[j], 0xffffffff);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 16:13:05 +02:00
|
|
|
fprintf(f, COLOR_CYAN " FMASK:" COLOR_RESET "\n");
|
|
|
|
|
for (unsigned j = 0; j < 8; j++)
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(f, gfx_level, family, sq_img_rsrc_word0 + j * 4, desc[8 + j], 0xffffffff);
|
2017-09-11 16:13:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_sampler_descriptor(enum amd_gfx_level gfx_level, enum radeon_family family, const uint32_t *desc, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
2024-04-15 19:10:42 +02:00
|
|
|
fprintf(f, COLOR_CYAN "Sampler state:" COLOR_RESET "\n");
|
2017-09-11 16:13:05 +02:00
|
|
|
for (unsigned j = 0; j < 4; j++) {
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(f, gfx_level, family, R_008F30_SQ_IMG_SAMP_WORD0 + j * 4, desc[j], 0xffffffff);
|
2017-09-11 16:13:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_combined_image_sampler_descriptor(enum amd_gfx_level gfx_level, enum radeon_family family,
|
|
|
|
|
const uint32_t *desc, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_image_descriptor(gfx_level, family, desc, f);
|
|
|
|
|
radv_dump_sampler_descriptor(gfx_level, family, desc + 16, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_descriptor_set(const struct radv_device *device, const struct radv_descriptor_set *set, unsigned id, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
enum amd_gfx_level gfx_level = pdev->info.gfx_level;
|
|
|
|
|
enum radeon_family family = pdev->info.family;
|
2017-09-11 16:13:05 +02:00
|
|
|
const struct radv_descriptor_set_layout *layout;
|
|
|
|
|
int i;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 16:13:05 +02:00
|
|
|
if (!set)
|
|
|
|
|
return;
|
2020-11-26 19:26:56 -08:00
|
|
|
layout = set->header.layout;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-11-26 19:26:56 -08:00
|
|
|
for (i = 0; i < set->header.layout->binding_count; i++) {
|
|
|
|
|
uint32_t *desc = set->header.mapped_ptr + layout->binding[i].offset / 4;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-15 19:10:42 +02:00
|
|
|
fprintf(f, "(set=%u binding=%u offset=0x%x) ", id, i, layout->binding[i].offset);
|
|
|
|
|
|
2017-09-11 16:13:05 +02:00
|
|
|
switch (layout->binding[i].type) {
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_buffer_descriptor(gfx_level, family, desc, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
break;
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_image_descriptor(gfx_level, family, desc, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
break;
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_combined_image_sampler_descriptor(gfx_level, family, desc, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
break;
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
2022-10-21 15:30:53 -04:00
|
|
|
radv_dump_sampler_descriptor(gfx_level, family, desc, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
break;
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
2022-09-15 13:10:27 +02:00
|
|
|
case VK_DESCRIPTOR_TYPE_MUTABLE_EXT:
|
2021-04-05 01:23:43 +02:00
|
|
|
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
|
2017-09-11 16:13:05 +02:00
|
|
|
/* todo */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(!"unknown descriptor type");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-10-15 15:32:13 +02:00
|
|
|
radv_dump_descriptors(struct radv_device *device, FILE *f)
|
2017-09-11 16:13:05 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2019-10-15 14:49:38 +02:00
|
|
|
fprintf(f, "Descriptors:\n");
|
2017-09-11 16:13:05 +02:00
|
|
|
for (i = 0; i < MAX_SETS; i++) {
|
2024-04-20 11:28:54 +02:00
|
|
|
struct radv_descriptor_set *set = (struct radv_descriptor_set *)(uintptr_t)device->trace_data->descriptor_sets[i];
|
2017-09-11 16:13:05 +02:00
|
|
|
|
2019-10-15 15:32:13 +02:00
|
|
|
radv_dump_descriptor_set(device, set, i, f);
|
2017-09-11 16:13:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
struct radv_shader_inst {
|
|
|
|
|
char text[160]; /* one disasm line */
|
|
|
|
|
unsigned offset; /* instruction offset */
|
2024-08-20 10:03:39 +02:00
|
|
|
unsigned size; /* instruction size >= 4 */
|
2017-09-11 13:44:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Split a disassembly string into lines and add them to the array pointed
|
|
|
|
|
* to by "instructions". */
|
|
|
|
|
static void
|
2024-01-02 15:42:02 +01:00
|
|
|
radv_add_split_disasm(const char *disasm, uint64_t start_addr, unsigned *num, struct radv_shader_inst *instructions)
|
2017-09-11 13:44:20 +02:00
|
|
|
{
|
|
|
|
|
struct radv_shader_inst *last_inst = *num ? &instructions[*num - 1] : NULL;
|
|
|
|
|
char *next;
|
2024-08-20 10:06:08 +02:00
|
|
|
char *repeat = strstr(disasm, "then repeated");
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
while ((next = strchr(disasm, '\n'))) {
|
|
|
|
|
struct radv_shader_inst *inst = &instructions[*num];
|
|
|
|
|
unsigned len = next - disasm;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-08-20 10:06:08 +02:00
|
|
|
if (repeat >= disasm && repeat < next) {
|
|
|
|
|
uint32_t repeat_count;
|
|
|
|
|
sscanf(repeat, "then repeated %u times", &repeat_count);
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < repeat_count; i++) {
|
|
|
|
|
inst = &instructions[*num];
|
|
|
|
|
memcpy(inst, last_inst, sizeof(struct radv_shader_inst));
|
|
|
|
|
inst->offset = last_inst->offset + last_inst->size * (i + 1);
|
|
|
|
|
(*num)++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_inst = inst;
|
|
|
|
|
|
|
|
|
|
disasm = next + 1;
|
|
|
|
|
repeat = strstr(disasm, "then repeated");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 13:42:57 +02:00
|
|
|
if (!memchr(disasm, ';', len)) {
|
|
|
|
|
/* Ignore everything that is not an instruction. */
|
|
|
|
|
disasm = next + 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
assert(len < ARRAY_SIZE(inst->text));
|
|
|
|
|
memcpy(inst->text, disasm, len);
|
|
|
|
|
inst->text[len] = 0;
|
|
|
|
|
inst->offset = last_inst ? last_inst->offset + last_inst->size : 0;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
const char *semicolon = strchr(disasm, ';');
|
|
|
|
|
assert(semicolon);
|
2024-08-20 10:03:39 +02:00
|
|
|
/* 9 = 8 hex digits + a leading space */
|
|
|
|
|
inst->size = (next - semicolon) / 9 * 4;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
snprintf(inst->text + len, ARRAY_SIZE(inst->text) - len, " [PC=0x%" PRIx64 ", off=%u, size=%u]",
|
|
|
|
|
start_addr + inst->offset, inst->offset, inst->size);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
last_inst = inst;
|
|
|
|
|
(*num)++;
|
|
|
|
|
disasm = next + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_annotated_shader(const struct radv_shader *shader, gl_shader_stage stage, struct ac_wave_info *waves,
|
2018-05-24 13:09:11 +02:00
|
|
|
unsigned num_waves, FILE *f)
|
2017-09-11 13:44:20 +02:00
|
|
|
{
|
|
|
|
|
uint64_t start_addr, end_addr;
|
|
|
|
|
unsigned i;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
if (!shader)
|
|
|
|
|
return;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-15 10:58:44 +02:00
|
|
|
start_addr = radv_shader_get_va(shader) & ((1ull << 48) - 1);
|
2017-09-11 13:44:20 +02:00
|
|
|
end_addr = start_addr + shader->code_size;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
/* See if any wave executes the shader. */
|
|
|
|
|
for (i = 0; i < num_waves; i++) {
|
|
|
|
|
if (start_addr <= waves[i].pc && waves[i].pc <= end_addr)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
if (i == num_waves)
|
|
|
|
|
return; /* the shader is not being executed */
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
/* Remember the first found wave. The waves are sorted according to PC. */
|
|
|
|
|
waves = &waves[i];
|
|
|
|
|
num_waves -= i;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
/* Get the list of instructions.
|
|
|
|
|
* Buffer size / 4 is the upper bound of the instruction count.
|
|
|
|
|
*/
|
|
|
|
|
unsigned num_inst = 0;
|
|
|
|
|
struct radv_shader_inst *instructions = calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-02 15:42:02 +01:00
|
|
|
radv_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n", radv_get_shader_name(&shader->info, stage));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
/* Print instructions with annotations. */
|
|
|
|
|
for (i = 0; i < num_inst; i++) {
|
|
|
|
|
struct radv_shader_inst *inst = &instructions[i];
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
fprintf(f, "%s\n", inst->text);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
/* Print which waves execute the instruction right now. */
|
|
|
|
|
while (num_waves && start_addr + inst->offset == waves->pc) {
|
|
|
|
|
fprintf(f,
|
|
|
|
|
" " COLOR_GREEN "^ SE%u SH%u CU%u "
|
|
|
|
|
"SIMD%u WAVE%u EXEC=%016" PRIx64 " ",
|
|
|
|
|
waves->se, waves->sh, waves->cu, waves->simd, waves->wave, waves->exec);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
if (inst->size == 4) {
|
|
|
|
|
fprintf(f, "INST32=%08X" COLOR_RESET "\n", waves->inst_dw0);
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(f, "INST64=%08X %08X" COLOR_RESET "\n", waves->inst_dw0, waves->inst_dw1);
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
waves->matched = true;
|
|
|
|
|
waves = &waves[1];
|
|
|
|
|
num_waves--;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2017-09-11 13:44:20 +02:00
|
|
|
fprintf(f, "\n\n");
|
|
|
|
|
free(instructions);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-27 11:12:04 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_spirv(const struct radv_shader *shader, const char *sha1, const char *dump_dir)
|
2021-05-27 11:12:04 +02:00
|
|
|
{
|
|
|
|
|
char dump_path[512];
|
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
|
|
snprintf(dump_path, sizeof(dump_path), "%s/%s.spv", dump_dir, sha1);
|
|
|
|
|
|
|
|
|
|
f = fopen(dump_path, "w+");
|
|
|
|
|
if (f) {
|
|
|
|
|
fwrite(shader->spirv, shader->spirv_size, 1, f);
|
|
|
|
|
fclose(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-05 21:07:57 +02:00
|
|
|
static void
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_shader(struct radv_device *device, struct radv_pipeline *pipeline, struct radv_shader *shader,
|
|
|
|
|
gl_shader_stage stage, const char *dump_dir, FILE *f)
|
2017-09-05 21:07:57 +02:00
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
|
2017-09-05 21:07:57 +02:00
|
|
|
if (!shader)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-07-11 18:03:55 +02:00
|
|
|
fprintf(f, "%s:\n\n", radv_get_shader_name(&shader->info, stage));
|
2017-09-22 16:44:08 +02:00
|
|
|
|
2017-09-22 16:56:40 +02:00
|
|
|
if (shader->spirv) {
|
2018-04-18 18:53:44 +02:00
|
|
|
unsigned char sha1[21];
|
|
|
|
|
char sha1buf[41];
|
|
|
|
|
|
|
|
|
|
_mesa_sha1_compute(shader->spirv, shader->spirv_size, sha1);
|
|
|
|
|
_mesa_sha1_format(sha1buf, sha1);
|
|
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
if (device->vk.enabled_features.deviceFaultVendorBinary) {
|
2024-08-27 10:17:30 -05:00
|
|
|
spirv_print_asm(f, (const uint32_t *)shader->spirv, shader->spirv_size / 4);
|
2024-01-26 09:39:44 +01:00
|
|
|
} else {
|
|
|
|
|
fprintf(f, "SPIRV (see %s.spv)\n\n", sha1buf);
|
|
|
|
|
radv_dump_spirv(shader, sha1buf, dump_dir);
|
|
|
|
|
}
|
2017-09-22 16:56:40 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-01 20:54:35 +02:00
|
|
|
if (shader->nir_string) {
|
|
|
|
|
fprintf(f, "NIR:\n%s\n", shader->nir_string);
|
2017-09-22 16:44:08 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-28 14:42:10 +01:00
|
|
|
fprintf(f, "%s IR:\n%s\n", pdev->use_llvm ? "LLVM" : "ACO", shader->ir_string);
|
2017-12-01 16:15:40 +01:00
|
|
|
fprintf(f, "DISASM:\n%s\n", shader->disasm_string);
|
2017-09-05 15:36:59 +02:00
|
|
|
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_shader_stats(device, pipeline, shader, stage, f);
|
2017-09-05 21:07:57 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-20 16:55:41 +01:00
|
|
|
static void
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_vertex_descriptors(const struct radv_device *device, const struct radv_graphics_pipeline *pipeline, FILE *f)
|
2020-11-20 16:55:41 +01:00
|
|
|
{
|
2023-03-29 15:49:47 +02:00
|
|
|
struct radv_shader *vs = radv_get_shader(pipeline->base.shaders, MESA_SHADER_VERTEX);
|
2023-03-29 16:21:52 +02:00
|
|
|
uint32_t count = util_bitcount(vs->info.vs.vb_desc_usage_mask);
|
2024-04-20 11:28:54 +02:00
|
|
|
uint32_t *vb_ptr = (uint32_t *)(uintptr_t)device->trace_data->vertex_descriptors;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-11-20 16:55:41 +01:00
|
|
|
if (!count)
|
|
|
|
|
return;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2023-03-29 15:49:47 +02:00
|
|
|
fprintf(f, "Num vertex %s: %d\n", vs->info.vs.use_per_attribute_vb_descs ? "attributes" : "bindings", count);
|
2020-11-20 16:55:41 +01:00
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
|
uint32_t *desc = &((uint32_t *)vb_ptr)[i * 4];
|
|
|
|
|
uint64_t va = 0;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-11-20 16:55:41 +01:00
|
|
|
va |= desc[0];
|
|
|
|
|
va |= (uint64_t)G_008F04_BASE_ADDRESS_HI(desc[1]) << 32;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-11-20 16:55:41 +01:00
|
|
|
fprintf(f, "VBO#%d:\n", i);
|
|
|
|
|
fprintf(f, "\tVA: 0x%" PRIx64 "\n", va);
|
|
|
|
|
fprintf(f, "\tStride: %d\n", G_008F04_STRIDE(desc[1]));
|
|
|
|
|
fprintf(f, "\tNum records: %d (0x%x)\n", desc[2], desc[2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-15 11:03:04 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_vs_prolog(const struct radv_device *device, const struct radv_graphics_pipeline *pipeline, FILE *f)
|
2021-10-15 11:03:04 +02:00
|
|
|
{
|
2024-04-20 11:28:54 +02:00
|
|
|
struct radv_shader_part *vs_prolog = (struct radv_shader_part *)(uintptr_t)device->trace_data->vertex_prolog;
|
2023-03-27 14:18:57 +02:00
|
|
|
struct radv_shader *vs_shader = radv_get_shader(pipeline->base.shaders, MESA_SHADER_VERTEX);
|
2021-10-15 11:03:04 +02:00
|
|
|
|
|
|
|
|
if (!vs_prolog || !vs_shader || !vs_shader->info.vs.has_prolog)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
fprintf(f, "Vertex prolog:\n\n");
|
|
|
|
|
fprintf(f, "DISASM:\n%s\n", vs_prolog->disasm_string);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-05 21:07:57 +02:00
|
|
|
static struct radv_pipeline *
|
2022-05-05 13:41:37 -04:00
|
|
|
radv_get_saved_pipeline(struct radv_device *device, enum amd_ip_type ring)
|
2017-09-05 21:07:57 +02:00
|
|
|
{
|
2024-04-20 11:28:54 +02:00
|
|
|
if (ring == AMD_IP_GFX)
|
|
|
|
|
return (struct radv_pipeline *)(uintptr_t)device->trace_data->gfx_ring_pipeline;
|
|
|
|
|
else
|
|
|
|
|
return (struct radv_pipeline *)(uintptr_t)device->trace_data->comp_ring_pipeline;
|
2017-09-05 21:07:57 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-26 17:34:28 +02:00
|
|
|
static void
|
2024-04-20 11:09:41 +02:00
|
|
|
radv_dump_queue_state(struct radv_queue *queue, const char *dump_dir, const char *wave_dump, FILE *f)
|
2017-09-05 21:07:57 +02:00
|
|
|
{
|
2024-04-01 12:33:10 +02:00
|
|
|
struct radv_device *device = radv_queue_device(queue);
|
2024-04-01 14:32:46 +02:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2022-05-05 13:41:37 -04:00
|
|
|
enum amd_ip_type ring = radv_queue_ring(queue);
|
2020-08-26 17:34:28 +02:00
|
|
|
struct radv_pipeline *pipeline;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-03-17 15:11:56 -04:00
|
|
|
fprintf(f, "AMD_IP_%s:\n", ac_get_ip_type_string(&pdev->info, ring));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-01 12:33:10 +02:00
|
|
|
pipeline = radv_get_saved_pipeline(device, ring);
|
2020-08-26 17:34:28 +02:00
|
|
|
if (pipeline) {
|
2023-10-26 11:58:40 +02:00
|
|
|
fprintf(f, "Pipeline hash: %" PRIx64 "\n", pipeline->pipeline_hash);
|
|
|
|
|
|
2022-05-24 12:04:19 +02:00
|
|
|
if (pipeline->type == RADV_PIPELINE_GRAPHICS) {
|
2022-12-12 09:02:43 +01:00
|
|
|
struct radv_graphics_pipeline *graphics_pipeline = radv_pipeline_to_graphics(pipeline);
|
2023-03-13 13:49:17 +01:00
|
|
|
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_vs_prolog(device, graphics_pipeline, f);
|
2023-03-13 13:49:17 +01:00
|
|
|
|
|
|
|
|
/* Dump active graphics shaders. */
|
|
|
|
|
unsigned stages = graphics_pipeline->active_stages;
|
|
|
|
|
while (stages) {
|
|
|
|
|
int stage = u_bit_scan(&stages);
|
|
|
|
|
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_shader(device, &graphics_pipeline->base, graphics_pipeline->base.shaders[stage], stage, dump_dir,
|
2023-03-13 13:49:17 +01:00
|
|
|
f);
|
|
|
|
|
}
|
2023-03-22 21:21:31 +01:00
|
|
|
} else if (pipeline->type == RADV_PIPELINE_RAY_TRACING) {
|
|
|
|
|
struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
|
|
|
|
|
for (unsigned i = 0; i < rt_pipeline->stage_count; i++) {
|
2023-09-12 17:39:45 +02:00
|
|
|
struct radv_shader *shader = rt_pipeline->stages[i].shader;
|
|
|
|
|
if (shader)
|
2023-03-22 21:21:31 +01:00
|
|
|
radv_dump_shader(device, pipeline, shader, shader->info.stage, dump_dir, f);
|
|
|
|
|
}
|
|
|
|
|
radv_dump_shader(device, pipeline, pipeline->shaders[MESA_SHADER_INTERSECTION], MESA_SHADER_INTERSECTION,
|
|
|
|
|
dump_dir, f);
|
2022-05-24 12:04:19 +02:00
|
|
|
} else {
|
2023-03-13 13:49:17 +01:00
|
|
|
struct radv_compute_pipeline *compute_pipeline = radv_pipeline_to_compute(pipeline);
|
|
|
|
|
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_shader(device, &compute_pipeline->base, compute_pipeline->base.shaders[MESA_SHADER_COMPUTE],
|
2023-03-13 13:49:17 +01:00
|
|
|
MESA_SHADER_COMPUTE, dump_dir, f);
|
2022-05-24 12:04:19 +02:00
|
|
|
}
|
2022-05-18 11:26:53 +02:00
|
|
|
|
2024-04-20 11:09:41 +02:00
|
|
|
if (wave_dump) {
|
2023-03-13 13:49:17 +01:00
|
|
|
struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP];
|
2024-03-28 14:42:10 +01:00
|
|
|
enum amd_gfx_level gfx_level = pdev->info.gfx_level;
|
2024-04-20 11:09:41 +02:00
|
|
|
unsigned num_waves = ac_get_wave_info(gfx_level, &pdev->info, wave_dump, waves);
|
2023-03-13 13:49:17 +01:00
|
|
|
|
|
|
|
|
fprintf(f, COLOR_CYAN "The number of active waves = %u" COLOR_RESET "\n\n", num_waves);
|
|
|
|
|
|
|
|
|
|
if (pipeline->type == RADV_PIPELINE_GRAPHICS) {
|
|
|
|
|
struct radv_graphics_pipeline *graphics_pipeline = radv_pipeline_to_graphics(pipeline);
|
|
|
|
|
|
|
|
|
|
/* Dump annotated active graphics shaders. */
|
|
|
|
|
unsigned stages = graphics_pipeline->active_stages;
|
|
|
|
|
while (stages) {
|
|
|
|
|
int stage = u_bit_scan(&stages);
|
|
|
|
|
|
|
|
|
|
radv_dump_annotated_shader(graphics_pipeline->base.shaders[stage], stage, waves, num_waves, f);
|
|
|
|
|
}
|
2023-03-22 21:21:31 +01:00
|
|
|
} else if (pipeline->type == RADV_PIPELINE_RAY_TRACING) {
|
|
|
|
|
struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
|
|
|
|
|
for (unsigned i = 0; i < rt_pipeline->stage_count; i++) {
|
2023-09-12 17:39:45 +02:00
|
|
|
struct radv_shader *shader = rt_pipeline->stages[i].shader;
|
|
|
|
|
if (shader)
|
2023-03-22 21:21:31 +01:00
|
|
|
radv_dump_annotated_shader(shader, shader->info.stage, waves, num_waves, f);
|
|
|
|
|
}
|
|
|
|
|
radv_dump_annotated_shader(pipeline->shaders[MESA_SHADER_INTERSECTION], MESA_SHADER_INTERSECTION, waves,
|
|
|
|
|
num_waves, f);
|
2023-03-13 13:49:17 +01:00
|
|
|
} else {
|
|
|
|
|
struct radv_compute_pipeline *compute_pipeline = radv_pipeline_to_compute(pipeline);
|
|
|
|
|
|
|
|
|
|
radv_dump_annotated_shader(compute_pipeline->base.shaders[MESA_SHADER_COMPUTE], MESA_SHADER_COMPUTE, waves,
|
|
|
|
|
num_waves, f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print waves executing shaders that are not currently bound. */
|
|
|
|
|
unsigned i;
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (i = 0; i < num_waves; i++) {
|
|
|
|
|
if (waves[i].matched)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
fprintf(f, COLOR_CYAN "Waves not executing currently-bound shaders:" COLOR_RESET "\n");
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
2024-04-15 12:44:50 +02:00
|
|
|
|
|
|
|
|
struct radv_shader *shader = radv_find_shader(device, waves[0].pc);
|
|
|
|
|
if (shader) {
|
|
|
|
|
radv_dump_annotated_shader(shader, shader->info.stage, waves, num_waves, f);
|
|
|
|
|
if (waves[i].matched)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-13 13:49:17 +01:00
|
|
|
fprintf(f, " SE%u SH%u CU%u SIMD%u WAVE%u EXEC=%016" PRIx64 " INST=%08X %08X PC=%" PRIx64 "\n",
|
|
|
|
|
waves[i].se, waves[i].sh, waves[i].cu, waves[i].simd, waves[i].wave, waves[i].exec,
|
|
|
|
|
waves[i].inst_dw0, waves[i].inst_dw1, waves[i].pc);
|
|
|
|
|
}
|
|
|
|
|
if (found)
|
|
|
|
|
fprintf(f, "\n\n");
|
|
|
|
|
}
|
2022-12-12 09:02:43 +01:00
|
|
|
|
2024-04-20 12:13:00 +02:00
|
|
|
VkDispatchIndirectCommand dispatch_indirect = device->trace_data->indirect_dispatch;
|
|
|
|
|
if (dispatch_indirect.x || dispatch_indirect.y || dispatch_indirect.z)
|
|
|
|
|
fprintf(f, "VkDispatchIndirectCommand: x=%u y=%u z=%u\n\n\n", dispatch_indirect.x, dispatch_indirect.y,
|
|
|
|
|
dispatch_indirect.z);
|
|
|
|
|
|
2022-12-12 09:02:43 +01:00
|
|
|
if (pipeline->type == RADV_PIPELINE_GRAPHICS) {
|
|
|
|
|
struct radv_graphics_pipeline *graphics_pipeline = radv_pipeline_to_graphics(pipeline);
|
2023-03-23 16:45:18 +01:00
|
|
|
radv_dump_vertex_descriptors(device, graphics_pipeline, f);
|
2022-12-12 09:02:43 +01:00
|
|
|
}
|
2024-04-01 12:33:10 +02:00
|
|
|
radv_dump_descriptors(device, f);
|
2020-08-26 17:34:28 +02:00
|
|
|
}
|
2017-09-05 21:07:57 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-11 22:02:54 +02:00
|
|
|
static void
|
2020-10-19 16:38:13 +02:00
|
|
|
radv_dump_cmd(const char *cmd, FILE *f)
|
2017-09-11 22:02:54 +02:00
|
|
|
{
|
2020-12-03 02:15:50 -08:00
|
|
|
#ifndef _WIN32
|
2020-10-19 16:38:13 +02:00
|
|
|
char line[2048];
|
2017-09-11 22:02:54 +02:00
|
|
|
FILE *p;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-10-19 16:38:13 +02:00
|
|
|
p = popen(cmd, "r");
|
|
|
|
|
if (p) {
|
|
|
|
|
while (fgets(line, sizeof(line), p))
|
|
|
|
|
fputs(line, f);
|
|
|
|
|
fprintf(f, "\n");
|
|
|
|
|
pclose(p);
|
|
|
|
|
}
|
2020-12-03 02:15:50 -08:00
|
|
|
#endif
|
2020-10-19 16:38:13 +02:00
|
|
|
}
|
2017-09-11 22:02:54 +02:00
|
|
|
|
2020-10-19 16:38:13 +02:00
|
|
|
static void
|
|
|
|
|
radv_dump_dmesg(FILE *f)
|
|
|
|
|
{
|
2017-09-11 22:02:54 +02:00
|
|
|
fprintf(f, "\nLast 60 lines of dmesg:\n\n");
|
2020-10-19 16:38:13 +02:00
|
|
|
radv_dump_cmd("dmesg | tail -n60", f);
|
2017-09-11 22:02:54 +02:00
|
|
|
}
|
|
|
|
|
|
2018-03-14 12:02:13 +01:00
|
|
|
void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_enabled_options(const struct radv_device *device, FILE *f)
|
2017-09-11 22:28:42 +02:00
|
|
|
{
|
2024-04-01 14:32:46 +02:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2024-04-01 14:51:07 +02:00
|
|
|
const struct radv_instance *instance = radv_physical_device_instance(pdev);
|
2017-09-11 22:28:42 +02:00
|
|
|
uint64_t mask;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-01 14:51:07 +02:00
|
|
|
if (instance->debug_flags) {
|
2018-03-14 12:01:49 +01:00
|
|
|
fprintf(f, "Enabled debug options: ");
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-01 14:51:07 +02:00
|
|
|
mask = instance->debug_flags;
|
2018-03-14 12:01:49 +01:00
|
|
|
while (mask) {
|
|
|
|
|
int i = u_bit_scan64(&mask);
|
|
|
|
|
fprintf(f, "%s, ", radv_get_debug_option_name(i));
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n");
|
2017-09-11 22:28:42 +02:00
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-01 14:51:07 +02:00
|
|
|
if (instance->perftest_flags) {
|
2018-03-14 12:01:49 +01:00
|
|
|
fprintf(f, "Enabled perftest options: ");
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-01 14:51:07 +02:00
|
|
|
mask = instance->perftest_flags;
|
2018-03-14 12:01:49 +01:00
|
|
|
while (mask) {
|
|
|
|
|
int i = u_bit_scan64(&mask);
|
|
|
|
|
fprintf(f, "%s, ", radv_get_perftest_option_name(i));
|
|
|
|
|
}
|
|
|
|
|
fprintf(f, "\n");
|
2017-09-11 22:28:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-20 09:48:13 +01:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_app_info(const struct radv_device *device, FILE *f)
|
2020-11-20 09:48:13 +01:00
|
|
|
{
|
2024-04-01 14:32:46 +02:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2024-04-01 14:51:07 +02:00
|
|
|
const struct radv_instance *instance = radv_physical_device_instance(pdev);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-01-25 10:35:32 +10:00
|
|
|
fprintf(f, "Application name: %s\n", instance->vk.app_info.app_name);
|
|
|
|
|
fprintf(f, "Application version: %d\n", instance->vk.app_info.app_version);
|
|
|
|
|
fprintf(f, "Engine name: %s\n", instance->vk.app_info.engine_name);
|
|
|
|
|
fprintf(f, "Engine version: %d\n", instance->vk.app_info.engine_version);
|
|
|
|
|
fprintf(f, "API version: %d.%d.%d\n", VK_VERSION_MAJOR(instance->vk.app_info.api_version),
|
|
|
|
|
VK_VERSION_MINOR(instance->vk.app_info.api_version), VK_VERSION_PATCH(instance->vk.app_info.api_version));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-11-20 09:48:13 +01:00
|
|
|
radv_dump_enabled_options(device, f);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-14 11:25:24 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_device_name(const struct radv_device *device, FILE *f)
|
2017-09-14 11:25:24 +02:00
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
const struct radeon_info *gpu_info = &pdev->info;
|
2020-12-03 02:15:50 -08:00
|
|
|
#ifndef _WIN32
|
2020-10-13 21:48:25 -07:00
|
|
|
char kernel_version[128] = {0};
|
2017-09-14 11:25:24 +02:00
|
|
|
struct utsname uname_data;
|
2020-12-03 02:15:50 -08:00
|
|
|
#endif
|
2017-09-14 11:25:24 +02:00
|
|
|
|
2020-12-03 02:15:50 -08:00
|
|
|
#ifdef _WIN32
|
2024-03-28 14:42:10 +01:00
|
|
|
fprintf(f, "Device name: %s (DRM %i.%i.%i)\n\n", pdev->marketing_name, gpu_info->drm_major, gpu_info->drm_minor,
|
|
|
|
|
gpu_info->drm_patchlevel);
|
2020-12-03 02:15:50 -08:00
|
|
|
#else
|
2017-09-14 11:25:24 +02:00
|
|
|
if (uname(&uname_data) == 0)
|
|
|
|
|
snprintf(kernel_version, sizeof(kernel_version), " / %s", uname_data.release);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-03-28 14:42:10 +01:00
|
|
|
fprintf(f, "Device name: %s (DRM %i.%i.%i%s)\n\n", pdev->marketing_name, gpu_info->drm_major, gpu_info->drm_minor,
|
|
|
|
|
gpu_info->drm_patchlevel, kernel_version);
|
2020-12-03 02:15:50 -08:00
|
|
|
#endif
|
2017-09-14 11:25:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-19 16:38:26 +02:00
|
|
|
static void
|
2023-05-16 02:57:54 +02:00
|
|
|
radv_dump_umr_ring(const struct radv_queue *queue, FILE *f)
|
2020-10-19 16:38:26 +02:00
|
|
|
{
|
2023-08-09 11:53:04 +02:00
|
|
|
#ifndef _WIN32
|
2024-04-01 12:33:10 +02:00
|
|
|
const struct radv_device *device = radv_queue_device(queue);
|
|
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2023-05-16 02:57:54 +02:00
|
|
|
const enum amd_ip_type ring = radv_queue_ring(queue);
|
2023-08-09 11:53:04 +02:00
|
|
|
char cmd[256];
|
2020-10-19 16:38:26 +02:00
|
|
|
|
|
|
|
|
/* TODO: Dump compute ring. */
|
2022-05-05 13:49:29 -04:00
|
|
|
if (ring != AMD_IP_GFX)
|
2020-10-19 16:38:26 +02:00
|
|
|
return;
|
|
|
|
|
|
2024-03-28 14:42:10 +01:00
|
|
|
sprintf(cmd, "umr --by-pci %04x:%02x:%02x.%01x -RS %s 2>&1", pdev->bus_info.domain, pdev->bus_info.bus,
|
|
|
|
|
pdev->bus_info.dev, pdev->bus_info.func, pdev->info.gfx_level >= GFX10 ? "gfx_0.0.0" : "gfx");
|
2020-10-19 16:38:26 +02:00
|
|
|
fprintf(f, "\nUMR GFX ring:\n\n");
|
|
|
|
|
radv_dump_cmd(cmd, f);
|
2023-08-09 11:53:04 +02:00
|
|
|
#endif
|
2020-10-19 16:38:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2024-04-20 11:09:41 +02:00
|
|
|
radv_dump_umr_waves(struct radv_queue *queue, const char *wave_dump, FILE *f)
|
2020-10-19 16:38:26 +02:00
|
|
|
{
|
2024-04-20 11:09:41 +02:00
|
|
|
fprintf(f, "\nUMR GFX waves:\n\n%s", wave_dump ? wave_dump : "");
|
2020-10-19 16:38:26 +02:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 09:44:45 +02:00
|
|
|
static bool
|
2023-04-12 07:18:46 +03:00
|
|
|
radv_gpu_hang_occurred(struct radv_queue *queue, enum amd_ip_type ring)
|
2017-09-01 09:44:45 +02:00
|
|
|
{
|
2024-04-01 12:33:10 +02:00
|
|
|
const struct radv_device *device = radv_queue_device(queue);
|
|
|
|
|
struct radeon_winsys *ws = device->ws;
|
2017-09-01 09:44:45 +02:00
|
|
|
|
2021-09-23 11:37:40 -05:00
|
|
|
if (!ws->ctx_wait_idle(queue->hw_ctx, ring, queue->vk.index_in_family))
|
2017-09-01 09:44:45 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-10 10:44:00 +02:00
|
|
|
bool
|
2023-10-10 10:43:38 +02:00
|
|
|
radv_vm_fault_occurred(struct radv_device *device, struct radv_winsys_gpuvm_fault_info *fault_info)
|
|
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
|
|
|
|
|
if (!pdev->info.has_gpuvm_fault_query)
|
2023-10-10 10:43:38 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return device->ws->query_gpuvm_fault(device->ws, fault_info);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-25 18:32:27 +01:00
|
|
|
enum radv_device_fault_chunk {
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_TRACE,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_QUEUE_STATE,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_UMR_WAVES,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_UMR_RING,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_REGISTERS,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_BO_RANGES,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_BO_HISTORY,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_VM_FAULT,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_APP_INFO,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_GPU_INFO,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_DMESG,
|
|
|
|
|
RADV_DEVICE_FAULT_CHUNK_COUNT,
|
|
|
|
|
};
|
|
|
|
|
|
2024-06-25 15:50:35 -06:00
|
|
|
VkResult
|
2023-07-25 08:07:29 +02:00
|
|
|
radv_check_gpu_hangs(struct radv_queue *queue, const struct radv_winsys_submit_info *submit_info)
|
2017-09-01 09:44:45 +02:00
|
|
|
{
|
2022-05-05 13:41:37 -04:00
|
|
|
enum amd_ip_type ring;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
radv: abstract queue family away from queue family index.
If we introduce another queue type (video decode) we can have a
disconnect between the RADV_QUEUE_ enum and the API queue_family_index.
currently the driver has
GENERAL, COMPUTE, TRANSFER which would end up at QFI 0, 1, <nothing>
since we don't create transfer.
Now if I add VDEC we get
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, 1, <nothing>, 2
or if you do nocompute
GENERAL, COMPUTE, TRANSFER, VDEC at QFI 0, <nothing>, <nothing>, 1
This means we have to add a remapping table between the API qfi
and the internal qf.
This patches tries to do that, in theory right now it just adds
overhead, but I'd like to exercise these paths.
v2: add radv_queue_ring abstraction, and pass physical device in,
as it makes adding uvd later easier.
v3: rename, and drop one direction as unneeded now, drop queue_family_index
from cmd_buffers.
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13687>
2021-11-05 16:03:24 +10:00
|
|
|
ring = radv_queue_ring(queue);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2023-04-12 07:18:46 +03:00
|
|
|
bool hang_occurred = radv_gpu_hang_occurred(queue, ring);
|
2023-10-24 09:29:41 +02:00
|
|
|
if (!hang_occurred)
|
2024-06-25 15:50:35 -06:00
|
|
|
return VK_SUCCESS;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-10-19 17:56:14 +02:00
|
|
|
fprintf(stderr, "radv: GPU hang detected...\n");
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-04-22 13:11:31 -07:00
|
|
|
#ifndef _WIN32
|
2024-04-01 12:33:10 +02:00
|
|
|
struct radv_device *device = radv_queue_device(queue);
|
|
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2024-04-01 14:51:07 +02:00
|
|
|
const struct radv_instance *instance = radv_physical_device_instance(pdev);
|
2024-04-01 12:33:10 +02:00
|
|
|
const bool save_hang_report = !device->vk.enabled_features.deviceFaultVendorBinary;
|
2023-10-10 10:43:38 +02:00
|
|
|
struct radv_winsys_gpuvm_fault_info fault_info = {0};
|
|
|
|
|
|
|
|
|
|
/* Query if a VM fault happened for this GPU hang. */
|
2024-04-01 12:33:10 +02:00
|
|
|
bool vm_fault_occurred = radv_vm_fault_occurred(device, &fault_info);
|
2023-10-10 10:43:38 +02:00
|
|
|
|
2020-11-20 09:19:55 +01:00
|
|
|
/* Create a directory into $HOME/radv_dumps_<pid>_<time> to save
|
|
|
|
|
* various debugging info about that GPU hang.
|
2020-10-19 17:56:14 +02:00
|
|
|
*/
|
2020-11-20 09:19:55 +01:00
|
|
|
struct tm *timep, result;
|
|
|
|
|
time_t raw_time;
|
2021-04-22 13:11:31 -07:00
|
|
|
FILE *f;
|
|
|
|
|
char dump_dir[256], dump_path[512], buf_time[128];
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
if (save_hang_report) {
|
|
|
|
|
time(&raw_time);
|
|
|
|
|
timep = os_localtime(&raw_time, &result);
|
|
|
|
|
strftime(buf_time, sizeof(buf_time), "%Y.%m.%d_%H.%M.%S", timep);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
snprintf(dump_dir, sizeof(dump_dir), "%s/" RADV_DUMP_DIR "_%d_%s", debug_get_option("HOME", "."), getpid(),
|
|
|
|
|
buf_time);
|
|
|
|
|
if (mkdir(dump_dir, 0774) && errno != EEXIST) {
|
|
|
|
|
fprintf(stderr, "radv: can't create directory '%s' (%i).\n", dump_dir, errno);
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
fprintf(stderr, "radv: GPU hang report will be saved to '%s'!\n", dump_dir);
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-25 18:32:27 +01:00
|
|
|
struct {
|
|
|
|
|
const char *name;
|
2024-01-26 09:39:44 +01:00
|
|
|
char *ptr;
|
|
|
|
|
size_t size;
|
2024-01-25 18:32:27 +01:00
|
|
|
} chunks[RADV_DEVICE_FAULT_CHUNK_COUNT] = {
|
|
|
|
|
{"trace"}, {"pipeline"}, {"umr_waves"}, {"umr_ring"}, {"registers"}, {"bo_ranges"},
|
|
|
|
|
{"bo_history"}, {"vm_fault"}, {"app_info"}, {"gpu_info"}, {"dmesg"},
|
|
|
|
|
};
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-20 11:09:41 +02:00
|
|
|
char *wave_dump = NULL;
|
|
|
|
|
if (!(instance->debug_flags & RADV_DEBUG_NO_UMR))
|
|
|
|
|
wave_dump = ac_get_umr_waves(&pdev->info, radv_queue_ring(queue));
|
|
|
|
|
|
2024-01-25 18:32:27 +01:00
|
|
|
for (uint32_t i = 0; i < RADV_DEVICE_FAULT_CHUNK_COUNT; i++) {
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
if (save_hang_report) {
|
|
|
|
|
snprintf(dump_path, sizeof(dump_path), "%s/%s.log", dump_dir, chunks[i].name);
|
|
|
|
|
|
|
|
|
|
f = fopen(dump_path, "w+");
|
|
|
|
|
} else {
|
|
|
|
|
f = open_memstream(&chunks[i].ptr, &chunks[i].size);
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-25 18:32:27 +01:00
|
|
|
if (!f)
|
|
|
|
|
continue;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-01-25 18:32:27 +01:00
|
|
|
switch (i) {
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_TRACE:
|
2024-04-01 12:33:10 +02:00
|
|
|
radv_dump_trace(device, submit_info->cs_array[0], f);
|
2024-01-25 18:32:27 +01:00
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_QUEUE_STATE:
|
2024-04-20 11:09:41 +02:00
|
|
|
radv_dump_queue_state(queue, dump_dir, wave_dump, f);
|
2024-01-25 18:32:27 +01:00
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_UMR_WAVES:
|
2024-04-01 14:51:07 +02:00
|
|
|
if (!(instance->debug_flags & RADV_DEBUG_NO_UMR))
|
2024-04-20 11:09:41 +02:00
|
|
|
radv_dump_umr_waves(queue, wave_dump, f);
|
2024-01-25 18:32:27 +01:00
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_UMR_RING:
|
2024-04-01 14:51:07 +02:00
|
|
|
if (!(instance->debug_flags & RADV_DEBUG_NO_UMR))
|
2024-01-25 18:32:27 +01:00
|
|
|
radv_dump_umr_ring(queue, f);
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_REGISTERS:
|
|
|
|
|
radv_dump_debug_registers(device, f);
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_BO_RANGES:
|
|
|
|
|
device->ws->dump_bo_ranges(device->ws, f);
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_BO_HISTORY:
|
|
|
|
|
device->ws->dump_bo_log(device->ws, f);
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_VM_FAULT:
|
|
|
|
|
if (vm_fault_occurred) {
|
|
|
|
|
fprintf(f, "VM fault report.\n\n");
|
|
|
|
|
fprintf(f, "Failing VM page: 0x%08" PRIx64 "\n", fault_info.addr);
|
2024-03-28 14:42:10 +01:00
|
|
|
ac_print_gpuvm_fault_status(f, pdev->info.gfx_level, fault_info.status);
|
2024-01-25 18:32:27 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_APP_INFO:
|
|
|
|
|
radv_dump_app_info(device, f);
|
|
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_GPU_INFO:
|
|
|
|
|
radv_dump_device_name(device, f);
|
2024-03-28 14:42:10 +01:00
|
|
|
ac_print_gpu_info(&pdev->info, f);
|
2024-01-25 18:32:27 +01:00
|
|
|
break;
|
|
|
|
|
case RADV_DEVICE_FAULT_CHUNK_DMESG:
|
|
|
|
|
radv_dump_dmesg(f);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2020-10-19 17:56:14 +02:00
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-10-19 17:56:14 +02:00
|
|
|
fclose(f);
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-04-20 11:09:41 +02:00
|
|
|
free(wave_dump);
|
|
|
|
|
|
2024-01-26 09:39:44 +01:00
|
|
|
if (save_hang_report) {
|
|
|
|
|
fprintf(stderr, "radv: GPU hang report saved successfully!\n");
|
|
|
|
|
abort();
|
|
|
|
|
} else {
|
|
|
|
|
char *report;
|
|
|
|
|
|
|
|
|
|
report = ralloc_strdup(NULL, "========== RADV GPU hang report ==========\n");
|
|
|
|
|
for (uint32_t i = 0; i < RADV_DEVICE_FAULT_CHUNK_COUNT; i++) {
|
|
|
|
|
if (!chunks[i].size)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ralloc_asprintf_append(&report, "\n========== %s ==========\n", chunks[i].name);
|
|
|
|
|
ralloc_asprintf_append(&report, "%s", chunks[i].ptr);
|
|
|
|
|
|
|
|
|
|
free(chunks[i].ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
device->gpu_hang_report = report;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
2024-06-25 15:50:35 -06:00
|
|
|
return VK_ERROR_DEVICE_LOST;
|
2017-09-01 09:44:45 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-18 18:51:46 +02:00
|
|
|
bool
|
|
|
|
|
radv_trap_handler_init(struct radv_device *device)
|
|
|
|
|
{
|
2024-05-16 17:50:57 +02:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2020-08-18 18:51:46 +02:00
|
|
|
struct radeon_winsys *ws = device->ws;
|
2021-02-09 13:47:28 +01:00
|
|
|
VkResult result;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:51:46 +02:00
|
|
|
/* Create the trap handler shader and upload it like other shaders. */
|
|
|
|
|
device->trap_handler_shader = radv_create_trap_handler_shader(device);
|
|
|
|
|
if (!device->trap_handler_shader) {
|
|
|
|
|
fprintf(stderr, "radv: failed to create the trap handler shader.\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2023-02-27 01:38:28 +09:00
|
|
|
result = ws->buffer_make_resident(ws, device->trap_handler_shader->bo, true);
|
2022-02-09 14:49:33 +01:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return false;
|
|
|
|
|
|
2024-03-25 14:54:08 +01:00
|
|
|
result = radv_bo_create(
|
2023-01-16 17:04:47 +01:00
|
|
|
device, NULL, TMA_BO_SIZE, 256, RADEON_DOMAIN_VRAM,
|
2021-04-28 02:10:57 +02:00
|
|
|
RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_ZERO_VRAM | RADEON_FLAG_32BIT,
|
2024-03-25 15:16:27 +01:00
|
|
|
RADV_BO_PRIORITY_SCRATCH, 0, true, &device->tma_bo);
|
2021-04-28 02:10:57 +02:00
|
|
|
if (result != VK_SUCCESS)
|
2020-08-18 18:51:46 +02:00
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-02-09 13:47:28 +01:00
|
|
|
result = ws->buffer_make_resident(ws, device->tma_bo, true);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-02-19 00:53:01 +01:00
|
|
|
device->tma_ptr = radv_buffer_map(ws, device->tma_bo);
|
2020-08-18 18:51:46 +02:00
|
|
|
if (!device->tma_ptr)
|
|
|
|
|
return false;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:51:46 +02:00
|
|
|
/* Upload a buffer descriptor to store various info from the trap. */
|
|
|
|
|
uint64_t tma_va = radv_buffer_get_va(device->tma_bo) + 16;
|
|
|
|
|
uint32_t desc[4];
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2024-05-16 17:50:57 +02:00
|
|
|
ac_build_raw_buffer_descriptor(pdev->info.gfx_level, tma_va, TMA_BO_SIZE, desc);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:51:46 +02:00
|
|
|
memcpy(device->tma_ptr, desc, sizeof(desc));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:51:46 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
radv_trap_handler_finish(struct radv_device *device)
|
|
|
|
|
{
|
|
|
|
|
struct radeon_winsys *ws = device->ws;
|
|
|
|
|
|
2021-02-09 13:47:28 +01:00
|
|
|
if (unlikely(device->trap_handler_shader)) {
|
2023-02-27 01:38:28 +09:00
|
|
|
ws->buffer_make_resident(ws, device->trap_handler_shader->bo, false);
|
|
|
|
|
radv_shader_unref(device, device->trap_handler_shader);
|
2021-02-09 13:47:28 +01:00
|
|
|
}
|
2020-08-18 18:51:46 +02:00
|
|
|
|
2021-02-09 13:47:28 +01:00
|
|
|
if (unlikely(device->tma_bo)) {
|
|
|
|
|
ws->buffer_make_resident(ws, device->tma_bo, false);
|
2023-01-16 17:04:47 +01:00
|
|
|
radv_bo_destroy(device, NULL, device->tma_bo);
|
2021-02-09 13:47:28 +01:00
|
|
|
}
|
2020-08-18 18:51:46 +02:00
|
|
|
}
|
2020-08-18 18:52:35 +02:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
radv_dump_faulty_shader(struct radv_device *device, uint64_t faulty_pc)
|
|
|
|
|
{
|
2021-10-27 13:20:29 +02:00
|
|
|
struct radv_shader *shader;
|
2020-08-18 18:52:35 +02:00
|
|
|
uint64_t start_addr, end_addr;
|
|
|
|
|
uint32_t instr_offset;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-10-27 13:20:29 +02:00
|
|
|
shader = radv_find_shader(device, faulty_pc);
|
2020-08-18 18:52:35 +02:00
|
|
|
if (!shader)
|
|
|
|
|
return;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2021-10-27 13:20:29 +02:00
|
|
|
start_addr = radv_shader_get_va(shader);
|
2020-08-18 18:52:35 +02:00
|
|
|
end_addr = start_addr + shader->code_size;
|
|
|
|
|
instr_offset = faulty_pc - start_addr;
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"Faulty shader found "
|
|
|
|
|
"VA=[0x%" PRIx64 "-0x%" PRIx64 "], instr_offset=%d\n",
|
|
|
|
|
start_addr, end_addr, instr_offset);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
/* Get the list of instructions.
|
|
|
|
|
* Buffer size / 4 is the upper bound of the instruction count.
|
|
|
|
|
*/
|
|
|
|
|
unsigned num_inst = 0;
|
|
|
|
|
struct radv_shader_inst *instructions = calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
/* Split the disassembly string into instructions. */
|
2024-01-02 15:42:02 +01:00
|
|
|
radv_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
/* Print instructions with annotations. */
|
|
|
|
|
for (unsigned i = 0; i < num_inst; i++) {
|
|
|
|
|
struct radv_shader_inst *inst = &instructions[i];
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
if (start_addr + inst->offset == faulty_pc) {
|
|
|
|
|
fprintf(stderr, "\n!!! Faulty instruction below !!!\n");
|
|
|
|
|
fprintf(stderr, "%s\n", inst->text);
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "%s\n", inst->text);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
free(instructions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct radv_sq_hw_reg {
|
|
|
|
|
uint32_t status;
|
|
|
|
|
uint32_t trap_sts;
|
|
|
|
|
uint32_t hw_id;
|
|
|
|
|
uint32_t ib_sts;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
radv_dump_sq_hw_regs(struct radv_device *device)
|
|
|
|
|
{
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
|
|
|
|
enum amd_gfx_level gfx_level = pdev->info.gfx_level;
|
|
|
|
|
enum radeon_family family = pdev->info.family;
|
2020-08-18 18:52:35 +02:00
|
|
|
struct radv_sq_hw_reg *regs = (struct radv_sq_hw_reg *)&device->tma_ptr[6];
|
2021-04-10 03:24:05 +02:00
|
|
|
|
2020-08-18 18:52:35 +02:00
|
|
|
fprintf(stderr, "\nHardware registers:\n");
|
2024-03-28 14:42:10 +01:00
|
|
|
if (pdev->info.gfx_level >= GFX10) {
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_000408_SQ_WAVE_STATUS, regs->status, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_00040C_SQ_WAVE_TRAPSTS, regs->trap_sts, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_00045C_SQ_WAVE_HW_ID1, regs->hw_id, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_00041C_SQ_WAVE_IB_STS, regs->ib_sts, ~0);
|
2020-08-21 08:09:58 -04:00
|
|
|
} else {
|
2022-10-21 15:30:53 -04:00
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_000048_SQ_WAVE_STATUS, regs->status, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_00004C_SQ_WAVE_TRAPSTS, regs->trap_sts, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_000050_SQ_WAVE_HW_ID, regs->hw_id, ~0);
|
|
|
|
|
ac_dump_reg(stderr, gfx_level, family, R_00005C_SQ_WAVE_IB_STS, regs->ib_sts, ~0);
|
2020-08-21 08:09:58 -04:00
|
|
|
}
|
2020-08-18 18:52:35 +02:00
|
|
|
fprintf(stderr, "\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
radv_check_trap_handler(struct radv_queue *queue)
|
|
|
|
|
{
|
2022-05-05 13:41:37 -04:00
|
|
|
enum amd_ip_type ring = radv_queue_ring(queue);
|
2024-04-01 12:33:10 +02:00
|
|
|
struct radv_device *device = radv_queue_device(queue);
|
2020-08-18 18:52:35 +02:00
|
|
|
struct radeon_winsys *ws = device->ws;
|
|
|
|
|
|
|
|
|
|
/* Wait for the context to be idle in a finite time. */
|
2021-09-23 11:37:40 -05:00
|
|
|
ws->ctx_wait_idle(queue->hw_ctx, ring, queue->vk.index_in_family);
|
2020-08-18 18:52:35 +02:00
|
|
|
|
|
|
|
|
/* Try to detect if the trap handler has been reached by the hw by
|
|
|
|
|
* looking at ttmp0 which should be non-zero if a shader exception
|
|
|
|
|
* happened.
|
|
|
|
|
*/
|
|
|
|
|
if (!device->tma_ptr[4])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
fprintf(stderr, "tma_ptr:\n");
|
|
|
|
|
for (unsigned i = 0; i < 10; i++)
|
|
|
|
|
fprintf(stderr, "tma_ptr[%d]=0x%x\n", i, device->tma_ptr[i]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
radv_dump_sq_hw_regs(device);
|
|
|
|
|
|
|
|
|
|
uint32_t ttmp0 = device->tma_ptr[4];
|
|
|
|
|
uint32_t ttmp1 = device->tma_ptr[5];
|
|
|
|
|
|
|
|
|
|
/* According to the ISA docs, 3.10 Trap and Exception Registers:
|
|
|
|
|
*
|
|
|
|
|
* "{ttmp1, ttmp0} = {3'h0, pc_rewind[3:0], HT[0], trapID[7:0], PC[47:0]}"
|
|
|
|
|
*
|
|
|
|
|
* "When the trap handler is entered, the PC of the faulting
|
|
|
|
|
* instruction is: (PC - PC_rewind * 4)."
|
|
|
|
|
* */
|
|
|
|
|
uint8_t trap_id = (ttmp1 >> 16) & 0xff;
|
|
|
|
|
uint8_t ht = (ttmp1 >> 24) & 0x1;
|
|
|
|
|
uint8_t pc_rewind = (ttmp1 >> 25) & 0xf;
|
|
|
|
|
uint64_t pc = (ttmp0 | ((ttmp1 & 0x0000ffffull) << 32)) - (pc_rewind * 4);
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "PC=0x%" PRIx64 ", trapID=%d, HT=%d, PC_rewind=%d\n", pc, trap_id, ht, pc_rewind);
|
|
|
|
|
|
|
|
|
|
radv_dump_faulty_shader(device, pc);
|
|
|
|
|
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2023-11-06 11:32:44 +01:00
|
|
|
|
|
|
|
|
/* VK_EXT_device_fault */
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
radv_GetDeviceFaultInfoEXT(VkDevice _device, VkDeviceFaultCountsEXT *pFaultCounts, VkDeviceFaultInfoEXT *pFaultInfo)
|
|
|
|
|
{
|
|
|
|
|
VK_OUTARRAY_MAKE_TYPED(VkDeviceFaultAddressInfoEXT, out, pFaultInfo ? pFaultInfo->pAddressInfos : NULL,
|
|
|
|
|
&pFaultCounts->addressInfoCount);
|
|
|
|
|
struct radv_winsys_gpuvm_fault_info fault_info = {0};
|
2024-04-02 18:06:21 +02:00
|
|
|
VK_FROM_HANDLE(radv_device, device, _device);
|
2024-03-28 14:42:10 +01:00
|
|
|
const struct radv_physical_device *pdev = radv_device_physical(device);
|
2024-04-01 14:51:07 +02:00
|
|
|
const struct radv_instance *instance = radv_physical_device_instance(pdev);
|
2023-11-06 11:32:44 +01:00
|
|
|
bool vm_fault_occurred = false;
|
|
|
|
|
|
|
|
|
|
/* Query if a GPUVM fault happened. */
|
|
|
|
|
vm_fault_occurred = radv_vm_fault_occurred(device, &fault_info);
|
|
|
|
|
|
|
|
|
|
/* No vendor-specific crash dumps yet. */
|
|
|
|
|
pFaultCounts->vendorInfoCount = 0;
|
|
|
|
|
pFaultCounts->vendorBinarySize = 0;
|
|
|
|
|
|
2024-01-26 09:42:49 +01:00
|
|
|
if (device->gpu_hang_report) {
|
|
|
|
|
VkDeviceFaultVendorBinaryHeaderVersionOneEXT hdr;
|
|
|
|
|
|
|
|
|
|
hdr.headerSize = sizeof(VkDeviceFaultVendorBinaryHeaderVersionOneEXT);
|
|
|
|
|
hdr.headerVersion = VK_DEVICE_FAULT_VENDOR_BINARY_HEADER_VERSION_ONE_EXT;
|
2024-03-28 11:25:10 +01:00
|
|
|
hdr.vendorID = pdev->vk.properties.vendorID;
|
|
|
|
|
hdr.deviceID = pdev->vk.properties.deviceID;
|
|
|
|
|
hdr.driverVersion = pdev->vk.properties.driverVersion;
|
|
|
|
|
memcpy(hdr.pipelineCacheUUID, pdev->cache_uuid, VK_UUID_SIZE);
|
2024-01-26 09:42:49 +01:00
|
|
|
hdr.applicationNameOffset = 0;
|
2024-04-01 14:51:07 +02:00
|
|
|
hdr.applicationVersion = instance->vk.app_info.app_version;
|
2024-01-26 09:42:49 +01:00
|
|
|
hdr.engineNameOffset = 0;
|
2024-04-01 14:51:07 +02:00
|
|
|
hdr.engineVersion = instance->vk.app_info.engine_version;
|
|
|
|
|
hdr.apiVersion = instance->vk.app_info.api_version;
|
2024-01-26 09:42:49 +01:00
|
|
|
|
|
|
|
|
pFaultCounts->vendorBinarySize = sizeof(hdr) + strlen(device->gpu_hang_report);
|
|
|
|
|
if (pFaultInfo) {
|
|
|
|
|
memcpy(pFaultInfo->pVendorBinaryData, &hdr, sizeof(hdr));
|
|
|
|
|
memcpy((char *)pFaultInfo->pVendorBinaryData + sizeof(hdr), device->gpu_hang_report,
|
|
|
|
|
strlen(device->gpu_hang_report));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 11:32:44 +01:00
|
|
|
if (vm_fault_occurred) {
|
|
|
|
|
VkDeviceFaultAddressInfoEXT addr_fault_info = {
|
2024-04-09 16:19:45 +02:00
|
|
|
.reportedAddress = ((int64_t)fault_info.addr << 16) >> 16,
|
2023-11-06 11:32:44 +01:00
|
|
|
.addressPrecision = 4096, /* 4K page granularity */
|
|
|
|
|
};
|
|
|
|
|
|
2024-01-26 14:13:10 +01:00
|
|
|
if (pFaultInfo)
|
|
|
|
|
strncpy(pFaultInfo->description, "A GPUVM fault has been detected", sizeof(pFaultInfo->description));
|
2023-11-06 11:32:44 +01:00
|
|
|
|
2024-03-28 14:42:10 +01:00
|
|
|
if (pdev->info.gfx_level >= GFX10) {
|
2023-11-06 11:32:44 +01:00
|
|
|
addr_fault_info.addressType = G_00A130_RW(fault_info.status) ? VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT
|
|
|
|
|
: VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT;
|
|
|
|
|
} else {
|
|
|
|
|
/* Not sure how to get the access status on GFX6-9. */
|
|
|
|
|
addr_fault_info.addressType = VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT;
|
|
|
|
|
}
|
|
|
|
|
vk_outarray_append_typed(VkDeviceFaultAddressInfoEXT, &out, elem) *elem = addr_fault_info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vk_outarray_status(&out);
|
|
|
|
|
}
|