From 4073cdf75364f25b1ed1ac853a53dd10d1c9e4d0 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Mon, 23 Mar 2026 10:49:32 +0000 Subject: [PATCH] radv: add radv_shader_debug_info Signed-off-by: Rhys Perry Reviewed-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_debug.c | 30 ++++++++++++------------- src/amd/vulkan/radv_pipeline.c | 12 +++++----- src/amd/vulkan/radv_pipeline_cache.c | 16 ++++++------- src/amd/vulkan/radv_pipeline_compute.c | 10 +++++---- src/amd/vulkan/radv_pipeline_graphics.c | 15 ++++++++----- src/amd/vulkan/radv_pipeline_rt.c | 10 +++++---- src/amd/vulkan/radv_shader.c | 30 ++++++++++++------------- src/amd/vulkan/radv_shader.h | 23 +++++++++++-------- 8 files changed, 80 insertions(+), 66 deletions(-) diff --git a/src/amd/vulkan/radv_debug.c b/src/amd/vulkan/radv_debug.c index 69fe37fe22e..7216434b61d 100644 --- a/src/amd/vulkan/radv_debug.c +++ b/src/amd/vulkan/radv_debug.c @@ -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++) { diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 7752146d190..8295605f793 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -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; diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c index 6b2da70343a..99f33064377 100644 --- a/src/amd/vulkan/radv_pipeline_cache.c +++ b/src/amd/vulkan/radv_pipeline_cache.c @@ -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); } diff --git a/src/amd/vulkan/radv_pipeline_compute.c b/src/amd/vulkan/radv_pipeline_compute.c index aeaa0f53be4..3486ef9a283 100644 --- a/src/amd/vulkan/radv_pipeline_compute.c +++ b/src/amd/vulkan/radv_pipeline_compute.c @@ -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; diff --git a/src/amd/vulkan/radv_pipeline_graphics.c b/src/amd/vulkan/radv_pipeline_graphics.c index a85c9dca9ee..380840e4d20 100644 --- a/src/amd/vulkan/radv_pipeline_graphics.c +++ b/src/amd/vulkan/radv_pipeline_graphics.c @@ -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; } } } diff --git a/src/amd/vulkan/radv_pipeline_rt.c b/src/amd/vulkan/radv_pipeline_rt.c index 14b4c75d8fc..9653e5dc7a1 100644 --- a/src/amd/vulkan/radv_pipeline_rt.c +++ b/src/amd/vulkan/radv_pipeline_rt.c @@ -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; } } diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index c9f3f0fdb0a..6e55f31bbbe 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -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: diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 7b8f4ba08aa..67ee618f45a 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -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 {