radv: add radv_shader_debug_info

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40627>
This commit is contained in:
Rhys Perry 2026-03-23 10:49:32 +00:00 committed by Marge Bot
parent 574f577657
commit 4073cdf753
8 changed files with 80 additions and 66 deletions

View file

@ -472,16 +472,16 @@ radv_dump_annotated_shader(const struct radv_shader *shader, mesa_shader_stage s
unsigned num_inst = 0;
struct radv_shader_inst *instructions = calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
radv_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
radv_add_split_disasm(shader->dbg.disasm_string, start_addr, &num_inst, instructions);
fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n", radv_get_shader_name(&shader->info, stage));
/* Maps a given offset inside the shader binary to a given debug_info index */
struct ac_shader_debug_info **debug_info_mapping = NULL;
if (shader->debug_info_count > 0) {
if (shader->dbg.debug_info_count > 0) {
debug_info_mapping = calloc(shader->code_size, sizeof(struct ac_shader_debug_info *));
for (uint32_t debug_index = 0; debug_index < shader->debug_info_count; debug_index++) {
struct ac_shader_debug_info *debug_info = &shader->debug_info[debug_index];
for (uint32_t debug_index = 0; debug_index < shader->dbg.debug_info_count; debug_index++) {
struct ac_shader_debug_info *debug_info = &shader->dbg.debug_info[debug_index];
if (debug_info->type != ac_shader_debug_info_src_loc)
continue;
@ -493,8 +493,8 @@ radv_dump_annotated_shader(const struct radv_shader *shader, mesa_shader_stage s
uint32_t range_end = shader->code_size; /* Last debug_info spans until the end of the shader */
if (debug_index + 1 <
shader->debug_info_count) { /* Only if there is another debug_info after the current one */
struct ac_shader_debug_info *next_debug_info = &shader->debug_info[debug_index + 1];
shader->dbg.debug_info_count) { /* Only if there is another debug_info after the current one */
struct ac_shader_debug_info *next_debug_info = &shader->dbg.debug_info[debug_index + 1];
range_end = next_debug_info->offset;
}
@ -553,7 +553,7 @@ radv_dump_spirv(const struct radv_shader *shader, const char *blake3, const char
f = fopen(dump_path, "w+");
if (f) {
fwrite(shader->spirv, shader->spirv_size, 1, f);
fwrite(shader->dbg.spirv, shader->dbg.spirv_size, 1, f);
fclose(f);
}
}
@ -569,27 +569,27 @@ radv_dump_shader(struct radv_device *device, struct radv_pipeline *pipeline, str
fprintf(f, "%s:\n\n", radv_get_shader_name(&shader->info, stage));
if (shader->spirv) {
if (shader->dbg.spirv) {
unsigned char blake3[BLAKE3_KEY_LEN + 1];
char blake3buf[BLAKE3_HEX_LEN];
_mesa_blake3_compute(shader->spirv, shader->spirv_size, blake3);
_mesa_blake3_compute(shader->dbg.spirv, shader->dbg.spirv_size, blake3);
_mesa_blake3_format(blake3buf, blake3);
if (device->vk.enabled_features.deviceFaultVendorBinary) {
spirv_print_asm(f, (const uint32_t *)shader->spirv, shader->spirv_size / 4);
spirv_print_asm(f, (const uint32_t *)shader->dbg.spirv, shader->dbg.spirv_size / 4);
} else {
fprintf(f, "SPIRV (see %s.spv)\n\n", blake3buf);
radv_dump_spirv(shader, blake3buf, dump_dir);
}
}
if (shader->nir_string) {
fprintf(f, "NIR:\n%s\n", shader->nir_string);
if (shader->dbg.nir_string) {
fprintf(f, "NIR:\n%s\n", shader->dbg.nir_string);
}
fprintf(f, "%s IR:\n%s\n", pdev->use_llvm ? "LLVM" : "ACO", shader->ir_string);
fprintf(f, "DISASM:\n%s\n", shader->disasm_string);
fprintf(f, "%s IR:\n%s\n", pdev->use_llvm ? "LLVM" : "ACO", shader->dbg.ir_string);
fprintf(f, "DISASM:\n%s\n", shader->dbg.disasm_string);
if (pipeline)
radv_dump_shader_stats(device, pipeline, shader, f);
@ -1202,7 +1202,7 @@ radv_dump_faulty_shader(const struct radv_device *device, const struct radv_shad
struct radv_shader_inst *instructions = calloc(shader->code_size / 4, sizeof(struct radv_shader_inst));
/* Split the disassembly string into instructions. */
radv_add_split_disasm(shader->disasm_string, start_addr, &num_inst, instructions);
radv_add_split_disasm(shader->dbg.disasm_string, start_addr, &num_inst, instructions);
/* Print instructions with annotations. */
for (unsigned i = 0; i < num_inst; i++) {

View file

@ -826,8 +826,8 @@ radv_GetPipelineExecutableStatisticsKHR(VkDevice _device, const VkPipelineExecut
VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableStatisticKHR, out, pStatistics, pStatisticCount);
struct amd_stats stats = {0};
if (shader->statistics)
stats = *shader->statistics;
if (shader->dbg.statistics)
stats = *shader->dbg.statistics;
stats.driverhash = pipeline->pipeline_hash;
stats.sgprs = shader->config.num_sgprs;
stats.vgprs = shader->config.num_vgprs;
@ -1012,7 +1012,7 @@ radv_GetPipelineExecutableInternalRepresentationsKHR(
p->isText = true;
VK_COPY_STR(p->name, "NIR Shader(s)");
VK_COPY_STR(p->description, "The optimized NIR shader(s)");
if (radv_copy_representation(p->pData, &p->dataSize, shader->nir_string) != VK_SUCCESS)
if (radv_copy_representation(p->pData, &p->dataSize, shader->dbg.nir_string) != VK_SUCCESS)
result = VK_INCOMPLETE;
}
++p;
@ -1027,17 +1027,17 @@ radv_GetPipelineExecutableInternalRepresentationsKHR(
VK_COPY_STR(p->name, "ACO IR");
VK_COPY_STR(p->description, "The ACO IR after some optimizations");
}
if (radv_copy_representation(p->pData, &p->dataSize, shader->ir_string) != VK_SUCCESS)
if (radv_copy_representation(p->pData, &p->dataSize, shader->dbg.ir_string) != VK_SUCCESS)
result = VK_INCOMPLETE;
}
++p;
/* Disassembler */
if (p < end && shader->disasm_string) {
if (p < end && shader->dbg.disasm_string) {
p->isText = true;
VK_COPY_STR(p->name, "Assembly");
VK_COPY_STR(p->description, "Final Assembly");
if (radv_copy_representation(p->pData, &p->dataSize, shader->disasm_string) != VK_SUCCESS)
if (radv_copy_representation(p->pData, &p->dataSize, shader->dbg.disasm_string) != VK_SUCCESS)
result = VK_INCOMPLETE;
}
++p;

View file

@ -52,12 +52,12 @@ radv_shader_destroy(struct vk_device *_device, struct vk_pipeline_cache_object *
radv_free_shader_memory(device, shader->alloc);
free(shader->code);
free(shader->spirv);
free(shader->nir_string);
free(shader->disasm_string);
free(shader->ir_string);
free(shader->statistics);
free(shader->debug_info);
free(shader->dbg.spirv);
free(shader->dbg.nir_string);
free(shader->dbg.disasm_string);
free(shader->dbg.ir_string);
free(shader->dbg.statistics);
free(shader->dbg.debug_info);
vk_pipeline_cache_object_finish(&shader->base);
free(shader);
@ -95,7 +95,7 @@ radv_shader_cache_deserialize(struct vk_pipeline_cache *cache, const void *key_d
void
radv_shader_serialize(struct radv_shader *shader, struct blob *blob)
{
size_t stats_size = shader->statistics ? sizeof(struct amd_stats) : 0;
size_t stats_size = shader->dbg.statistics ? sizeof(struct amd_stats) : 0;
size_t code_size = shader->code_size;
uint32_t total_size = sizeof(struct radv_shader_binary_legacy) + code_size + stats_size;
@ -115,7 +115,7 @@ radv_shader_serialize(struct radv_shader *shader, struct blob *blob)
};
blob_write_bytes(blob, &binary, sizeof(struct radv_shader_binary_legacy));
blob_write_bytes(blob, shader->statistics, stats_size);
blob_write_bytes(blob, shader->dbg.statistics, stats_size);
blob_write_bytes(blob, shader->code, code_size);
}

View file

@ -138,7 +138,9 @@ radv_compile_cs(struct radv_device *device, struct vk_pipeline_cache *cache, str
cs_shader = radv_shader_create(device, cache, *cs_binary, skip_shaders_cache || dump_shader);
cs_shader->nir_string = nir_string;
cs_shader->dbg.nir_string = nir_string;
cs_shader->dbg.stages = 1 << MESA_SHADER_COMPUTE;
cs_shader->dbg.dump_shader = dump_shader;
radv_shader_dump_debug_info(device, dump_shader, *cs_binary, cs_shader, &cs_stage->nir, 1, &cs_stage->info);
@ -146,9 +148,9 @@ radv_compile_cs(struct radv_device *device, struct vk_pipeline_cache *cache, str
simple_mtx_unlock(&instance->shader_dump_mtx);
if (keep_executable_info && cs_stage->spirv.size) {
cs_shader->spirv = malloc(cs_stage->spirv.size);
memcpy(cs_shader->spirv, cs_stage->spirv.data, cs_stage->spirv.size);
cs_shader->spirv_size = cs_stage->spirv.size;
cs_shader->dbg.spirv = malloc(cs_stage->spirv.size);
memcpy(cs_shader->dbg.spirv, cs_stage->spirv.data, cs_stage->spirv.size);
cs_shader->dbg.spirv_size = cs_stage->spirv.size;
}
return cs_shader;

View file

@ -2427,7 +2427,9 @@ radv_create_gs_copy_shader(struct radv_device *device, struct vk_pipeline_cache
radv_shader_create(device, cache, *gs_copy_binary, skip_shaders_cache || dump_shader);
if (copy_shader) {
copy_shader->nir_string = nir_string;
copy_shader->dbg.nir_string = nir_string;
copy_shader->dbg.stages = 1 << MESA_SHADER_VERTEX;
copy_shader->dbg.dump_shader = dump_shader;
radv_shader_dump_debug_info(device, dump_shader, *gs_copy_binary, copy_shader, &nir, 1, &gs_copy_stage.info);
}
@ -2500,7 +2502,10 @@ radv_graphics_shaders_nir_to_asm(struct radv_device *device, struct vk_pipeline_
shaders[s] = radv_shader_create(device, cache, binaries[s], skip_shaders_cache || dump_shader);
shaders[s]->nir_string = nir_string;
shaders[s]->dbg.nir_string = nir_string;
for (uint32_t i = 0; i < shader_count; i++)
shaders[s]->dbg.stages |= 1 << nir_shaders[i]->info.stage;
shaders[s]->dbg.dump_shader = dump_shader;
radv_shader_dump_debug_info(device, dump_shader, binaries[s], shaders[s], nir_shaders, shader_count,
&stages[s].info);
@ -2956,9 +2961,9 @@ radv_graphics_shaders_compile(struct radv_device *device, struct vk_pipeline_cac
if (!stages[i].spirv.size)
continue;
shader->spirv = malloc(stages[i].spirv.size);
memcpy(shader->spirv, stages[i].spirv.data, stages[i].spirv.size);
shader->spirv_size = stages[i].spirv.size;
shader->dbg.spirv = malloc(stages[i].spirv.size);
memcpy(shader->dbg.spirv, stages[i].spirv.data, stages[i].spirv.size);
shader->dbg.spirv_size = stages[i].spirv.size;
}
}
}

View file

@ -526,7 +526,9 @@ radv_rt_nir_to_asm(struct radv_device *device, struct vk_pipeline_cache *cache,
shader = radv_shader_create(device, cache, binary, skip_shaders_cache || dump_shader);
if (shader) {
shader->nir_string = nir_string;
shader->dbg.nir_string = nir_string;
shader->dbg.stages = 1 << shaders[0]->info.stage;
shader->dbg.dump_shader = dump_shader;
if (stack_size)
*stack_size = DIV_ROUND_UP(shader->config.scratch_bytes_per_wave, shader->info.wave_size);
@ -534,9 +536,9 @@ radv_rt_nir_to_asm(struct radv_device *device, struct vk_pipeline_cache *cache,
radv_shader_dump_debug_info(device, dump_shader, binary, shader, shaders, num_shaders, &stage->info);
if (shader && keep_executable_info && stage->spirv.size) {
shader->spirv = malloc(stage->spirv.size);
memcpy(shader->spirv, stage->spirv.data, stage->spirv.size);
shader->spirv_size = stage->spirv.size;
shader->dbg.spirv = malloc(stage->spirv.size);
memcpy(shader->dbg.spirv, stage->spirv.data, stage->spirv.size);
shader->dbg.spirv_size = stage->spirv.size;
}
}

View file

@ -2909,10 +2909,10 @@ radv_shader_create_uncached(struct radv_device *device, const struct radv_shader
goto out;
}
shader->ir_string = bin->llvm_ir_size ? strdup((const char *)(bin->data + bin->elf_size)) : NULL;
shader->disasm_string = malloc(disasm_size + 1);
memcpy(shader->disasm_string, disasm_data, disasm_size);
shader->disasm_string[disasm_size] = 0;
shader->dbg.ir_string = bin->llvm_ir_size ? strdup((const char *)(bin->data + bin->elf_size)) : NULL;
shader->dbg.disasm_string = malloc(disasm_size + 1);
memcpy(shader->dbg.disasm_string, disasm_data, disasm_size);
shader->dbg.disasm_string[disasm_size] = 0;
ac_rtld_close(&rtld_binary);
#endif
@ -2924,17 +2924,17 @@ radv_shader_create_uncached(struct radv_device *device, const struct radv_shader
shader->exec_size = bin->exec_size;
if (bin->stats_size) {
shader->statistics = calloc(bin->stats_size, 1);
memcpy(shader->statistics, layout.stats, bin->stats_size);
shader->dbg.statistics = calloc(bin->stats_size, 1);
memcpy(shader->dbg.statistics, layout.stats, bin->stats_size);
}
shader->ir_string = bin->ir_size ? strdup(layout.ir) : NULL;
shader->disasm_string = bin->disasm_size ? strdup(layout.disasm) : NULL;
shader->dbg.ir_string = bin->ir_size ? strdup(layout.ir) : NULL;
shader->dbg.disasm_string = bin->disasm_size ? strdup(layout.disasm) : NULL;
if (bin->debug_info_size) {
shader->debug_info = malloc(bin->debug_info_size);
memcpy(shader->debug_info, layout.debug_info, bin->debug_info_size);
shader->debug_info_count = bin->debug_info_size / sizeof(struct ac_shader_debug_info);
shader->dbg.debug_info = malloc(bin->debug_info_size);
memcpy(shader->dbg.debug_info, layout.debug_info, bin->debug_info_size);
shader->dbg.debug_info_count = bin->debug_info_size / sizeof(struct ac_shader_debug_info);
}
}
@ -3363,7 +3363,7 @@ radv_shader_dump_debug_info(struct radv_device *device, bool dump_shader, struct
for (int i = 1; i < shader_count; ++i)
fprintf(stderr, " + %s", radv_get_shader_name(info, shaders[i]->info.stage));
fprintf(stderr, "\ndisasm:\n%s\n", shader->disasm_string);
fprintf(stderr, "\ndisasm:\n%s\n", shader->dbg.disasm_string);
}
}
}
@ -3414,10 +3414,10 @@ radv_create_trap_handler_shader(struct radv_device *device)
if (options.dump_shader) {
fprintf(stderr, "Trap handler");
fprintf(stderr, "\ndisasm:\n%s\n", shader->disasm_string);
fprintf(stderr, "\ndisasm:\n%s\n", shader->dbg.disasm_string);
}
free(shader->disasm_string);
free(shader->dbg.disasm_string);
ralloc_free(b.shader);
free(binary);
@ -3498,7 +3498,7 @@ radv_create_rt_prolog(struct radv_device *device, unsigned raygen_param_count, n
if (options.dump_shader) {
fprintf(stderr, "Raytracing prolog");
fprintf(stderr, "\ndisasm:\n%s\n", prolog->disasm_string);
fprintf(stderr, "\ndisasm:\n%s\n", prolog->dbg.disasm_string);
}
done:

View file

@ -414,6 +414,19 @@ struct radv_serialized_shader_arena_block {
uint32_t arena_size;
};
struct radv_shader_debug_info {
bool dump_shader;
uint32_t stages; /* mesa_shader_stage */
char *spirv;
uint32_t spirv_size;
char *nir_string;
char *disasm_string;
char *ir_string;
struct amd_stats *statistics;
struct ac_shader_debug_info *debug_info;
uint32_t debug_info_count;
};
struct radv_shader {
struct vk_pipeline_cache_object base;
@ -436,15 +449,7 @@ struct radv_shader {
blake3_hash hash;
void *code;
/* debug only */
char *spirv;
uint32_t spirv_size;
char *nir_string;
char *disasm_string;
char *ir_string;
struct amd_stats *statistics;
struct ac_shader_debug_info *debug_info;
uint32_t debug_info_count;
struct radv_shader_debug_info dbg;
};
struct radv_shader_part {