From 37789249a10218d7845d025b3c8b7dcca3dfbf56 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 9 Dec 2025 12:36:36 +0200 Subject: [PATCH] anv: fix internal representations of shaders The shader assembly was only available when not hitting the cache. Additionally the serialized shader code was also the relocated variant which meant that it could differ from one run to the next. Instead serialize the unrelocated code produced by the compiler. With this change we now decode the copy of the ISA we have on the host. NIR dumps are only available for shaders not loaded from the cache (much like the other drivers). Signed-off-by: Lionel Landwerlin Fixes: 8f4c2bd566 ("anv: add runtime shader statistic support") Acked-by: Michael Cheng Part-of: --- src/intel/vulkan/anv_private.h | 3 +- src/intel/vulkan/anv_shader.c | 241 ++++++++++++++++++--------------- 2 files changed, 136 insertions(+), 108 deletions(-) diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 0b6bffd0753..49472aa7d2e 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1233,6 +1233,8 @@ struct anv_gfx_state_ptr { struct anv_shader { struct vk_shader vk; + void *code; + struct anv_state kernel; const struct brw_stage_prog_data *prog_data; @@ -1241,7 +1243,6 @@ struct anv_shader { uint32_t num_stats; char *nir_str; - char *asm_str; struct nir_xfb_info *xfb_info; diff --git a/src/intel/vulkan/anv_shader.c b/src/intel/vulkan/anv_shader.c index 26161ddb15e..de8ceb59c6b 100644 --- a/src/intel/vulkan/anv_shader.c +++ b/src/intel/vulkan/anv_shader.c @@ -106,8 +106,7 @@ anv_shader_serialize(struct vk_device *device, blob_write_uint32(blob, vk_shader->stage); blob_write_uint32(blob, shader->prog_data->program_size); - blob_write_bytes(blob, shader->kernel.map, - shader->prog_data->program_size); + blob_write_bytes(blob, shader->code, shader->prog_data->program_size); union brw_any_prog_data prog_data; memcpy(&prog_data, shader->prog_data, brw_prog_data_size(vk_shader->stage)); @@ -255,14 +254,125 @@ write_ir_text(VkPipelineExecutableInternalRepresentationKHR* ir, return true; } +static char * +get_shader_bind_map_text(const struct anv_shader *shader) +{ + char *stream_data = NULL; + size_t stream_size = 0; + FILE *stream = open_memstream(&stream_data, &stream_size); + + const struct anv_pipeline_bind_map *bind_map = &shader->bind_map; + uint32_t push_size = 0; + for (unsigned i = 0; i < 4; i++) + push_size += bind_map->push_ranges[i].length; + if (push_size > 0) { + fprintf(stream, "Push constant ranges:\n"); + for (unsigned i = 0; i < 4; i++) { + if (bind_map->push_ranges[i].length == 0) + continue; + + fprintf(stream, " RANGE%d (%dB): ", i, + bind_map->push_ranges[i].length * 32); + + switch (bind_map->push_ranges[i].set) { + case ANV_DESCRIPTOR_SET_NULL: + fprintf(stream, "NULL"); + break; + + case ANV_DESCRIPTOR_SET_PUSH_CONSTANTS: + fprintf(stream, "Vulkan push constants and API params"); + break; + + case ANV_DESCRIPTOR_SET_DESCRIPTORS_BUFFER: + fprintf(stream, "Descriptor buffer (desc buffer) for set %d (start=%dB)", + bind_map->push_ranges[i].index, + bind_map->push_ranges[i].start * 32); + break; + + case ANV_DESCRIPTOR_SET_DESCRIPTORS: + fprintf(stream, "Descriptor buffer for set %d (start=%dB)", + bind_map->push_ranges[i].index, + bind_map->push_ranges[i].start * 32); + break; + + case ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS: + UNREACHABLE("Color attachments can't be pushed"); + + case ANV_DESCRIPTOR_SET_PER_PRIM_PADDING: + fprintf(stream, "Per primitive alignment (gfx libs & mesh)"); + break; + + default: + fprintf(stream, "UBO (set=%d binding=%d start=%dB)", + bind_map->push_ranges[i].set, + bind_map->push_ranges[i].index, + bind_map->push_ranges[i].start * 32); + break; + } + fprintf(stream, "\n"); + } + fprintf(stream, "\n"); + + } + + fclose(stream); + + if (stream_size == 0) { + free(stream_data); + return NULL; + } + + return stream_data; +} + +static char * +get_shader_isa_text(struct anv_device *device, + const struct anv_shader *shader, + uint32_t executable_index) +{ + char *stream_data = NULL; + size_t stream_size = 0; + FILE *stream = open_memstream(&stream_data, &stream_size); + + if (shader->vk.stage == MESA_SHADER_FRAGMENT) { + const struct brw_wm_prog_data *wm_prog_data = get_shader_wm_prog_data(shader); + + int simd8_index = (wm_prog_data->dispatch_8 || wm_prog_data->dispatch_multi) ? 0 : -1; + int simd16_index = wm_prog_data->dispatch_16 ? (simd8_index + 1) : -1; + int simd32_index = wm_prog_data->dispatch_32 ? (MAX2(simd8_index, simd16_index) + 1) : -1; + + if (executable_index == simd8_index) { + brw_disassemble_with_errors(&device->physical->compiler->isa, + shader->code, 0, NULL, stream); + } else if (executable_index == simd16_index) { + brw_disassemble_with_errors(&device->physical->compiler->isa, + shader->code, + wm_prog_data->prog_offset_16, NULL, stream); + } else if (executable_index == simd32_index) { + brw_disassemble_with_errors(&device->physical->compiler->isa, + shader->code, + wm_prog_data->prog_offset_32, NULL, stream); + } + } else { + brw_disassemble_with_errors(&device->physical->compiler->isa, + shader->code, 0, NULL, stream); + } + + fclose(stream); + + return stream_data; +} + static VkResult anv_shader_get_executable_internal_representations( - struct vk_device *device, + struct vk_device *vk_device, const struct vk_shader *vk_shader, uint32_t executable_index, uint32_t *internal_representation_count, VkPipelineExecutableInternalRepresentationKHR *internal_representations) { + struct anv_device *device = + container_of(vk_device, struct anv_device, vk); VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableInternalRepresentationKHR, out, internal_representations, internal_representation_count); @@ -282,16 +392,30 @@ anv_shader_get_executable_internal_representations( } } - if (shader->asm_str) { + char *bind_map_text = get_shader_bind_map_text(shader); + if (bind_map_text != NULL) { + vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, &out, ir) { + VK_COPY_STR(ir->name, "Shader push map"); + VK_COPY_STR(ir->description, "Map of push constant data provided to the shader"); + + if (!write_ir_text(ir, bind_map_text)) + incomplete_text = true; + } + } + free(bind_map_text); + + char *isa_text = get_shader_isa_text(device, shader, executable_index); + if (isa_text != NULL) { vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, &out, ir) { VK_COPY_STR(ir->name, "GEN Assembly"); VK_COPY_STR(ir->description, "Final GEN assembly for the generated shader binary"); - if (!write_ir_text(ir, shader->asm_str)) + if (!write_ir_text(ir, isa_text)) incomplete_text = true; } } + free(isa_text); return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out); } @@ -426,8 +550,6 @@ anv_shader_reloc(struct anv_device *device, struct internal_representation { char *nir_str; uint32_t nir_str_len; - char *asm_str; - uint32_t asm_str_len; }; static void @@ -440,102 +562,6 @@ get_internal_representation_data(struct internal_representation *output, output->nir_str = nir_shader_as_str(shader_data->info->nir, mem_ctx); output->nir_str_len = strlen(output->nir_str) + 1; - - char *stream_data = NULL; - size_t stream_size = 0; - FILE *stream = open_memstream(&stream_data, &stream_size); - - const struct anv_pipeline_bind_map *bind_map = &shader_data->bind_map; - uint32_t push_size = 0; - for (unsigned i = 0; i < 4; i++) - push_size += bind_map->push_ranges[i].length; - if (push_size > 0) { - fprintf(stream, "Push constant ranges:\n"); - for (unsigned i = 0; i < 4; i++) { - if (bind_map->push_ranges[i].length == 0) - continue; - - fprintf(stream, " RANGE%d (%dB): ", i, - bind_map->push_ranges[i].length * 32); - - switch (bind_map->push_ranges[i].set) { - case ANV_DESCRIPTOR_SET_NULL: - fprintf(stream, "NULL"); - break; - - case ANV_DESCRIPTOR_SET_PUSH_CONSTANTS: - fprintf(stream, "Vulkan push constants and API params"); - break; - - case ANV_DESCRIPTOR_SET_DESCRIPTORS_BUFFER: - fprintf(stream, "Descriptor buffer (desc buffer) for set %d (start=%dB)", - bind_map->push_ranges[i].index, - bind_map->push_ranges[i].start * 32); - break; - - case ANV_DESCRIPTOR_SET_DESCRIPTORS: - fprintf(stream, "Descriptor buffer for set %d (start=%dB)", - bind_map->push_ranges[i].index, - bind_map->push_ranges[i].start * 32); - break; - - case ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS: - UNREACHABLE("Color attachments can't be pushed"); - - case ANV_DESCRIPTOR_SET_PER_PRIM_PADDING: - fprintf(stream, "Per primitive alignment (gfx libs & mesh)"); - break; - - default: - fprintf(stream, "UBO (set=%d binding=%d start=%dB)", - bind_map->push_ranges[i].set, - bind_map->push_ranges[i].index, - bind_map->push_ranges[i].start * 32); - break; - } - fprintf(stream, "\n"); - } - fprintf(stream, "\n"); - - } - - /* Creating this is far cheaper than it looks. It's perfectly fine to - * do it for every binary. - */ - if (shader_data->info->stage == MESA_SHADER_FRAGMENT) { - const struct brw_wm_prog_data *wm_prog_data = &shader_data->prog_data.wm; - - if (wm_prog_data->dispatch_8 || - wm_prog_data->dispatch_multi) { - brw_disassemble_with_errors(&device->physical->compiler->isa, - shader_data->code, 0, NULL, stream); - } - - if (wm_prog_data->dispatch_16) { - brw_disassemble_with_errors(&device->physical->compiler->isa, - shader_data->code, - wm_prog_data->prog_offset_16, NULL, stream); - } - - if (wm_prog_data->dispatch_32) { - brw_disassemble_with_errors(&device->physical->compiler->isa, - shader_data->code, - wm_prog_data->prog_offset_32, NULL, stream); - } - } else { - brw_disassemble_with_errors(&device->physical->compiler->isa, - shader_data->code, 0, NULL, stream); - } - - fclose(stream); - - /* Copy it to a ralloc'd thing */ - output->asm_str = ralloc_size(mem_ctx, stream_size + 1); - memcpy(output->asm_str, stream_data, stream_size); - output->asm_str[stream_size] = 0; - output->asm_str_len = stream_size + 1; - - free(stream_data); } VkResult @@ -574,6 +600,7 @@ anv_shader_create(struct anv_device *device, shader_data->xfb_info == NULL ? 0 : nir_xfb_info_size(shader_data->xfb_info->output_count)); + VK_MULTIALLOC_DECL(&ma, void, code, shader_data->prog_data.base.program_size); VK_MULTIALLOC_DECL(&ma, struct anv_pipeline_binding, surface_to_descriptor, shader_data->bind_map.surface_count); VK_MULTIALLOC_DECL(&ma, struct anv_pipeline_binding, sampler_to_descriptor, @@ -584,7 +611,6 @@ anv_shader_create(struct anv_device *device, VK_MULTIALLOC_DECL(&ma, struct anv_embedded_sampler *, embedded_samplers, shader_data->bind_map.embedded_sampler_count); VK_MULTIALLOC_DECL(&ma, char, nir_str, internal_representations.nir_str_len); - VK_MULTIALLOC_DECL(&ma, char, asm_str, internal_representations.asm_str_len); if (!vk_shader_multizalloc(&device->vk, &ma, &anv_shader_ops, stage, pAllocator)) @@ -599,6 +625,10 @@ anv_shader_create(struct anv_device *device, goto error_shader; } + shader->code = code; + memcpy(shader->code, shader_data->code, + shader_data->prog_data.base.program_size); + shader->kernel = anv_state_pool_alloc(&device->instruction_state_pool, shader_data->prog_data.base.program_size, 64); @@ -611,9 +641,6 @@ anv_shader_create(struct anv_device *device, shader->nir_str = nir_str; memcpy(shader->nir_str, internal_representations.nir_str, internal_representations.nir_str_len); - shader->asm_str = asm_str; - memcpy(shader->asm_str, internal_representations.asm_str, - internal_representations.asm_str_len); } memcpy(prog_data, &shader_data->prog_data, brw_prog_data_size(stage));