From 4dbc0feae2eebeac06ca9f41dfcc30df8fc951fa Mon Sep 17 00:00:00 2001 From: Mary Guillemard Date: Mon, 13 May 2024 10:40:30 +0200 Subject: [PATCH] panvk: Implement executable IR reporting This report the NIR shader before sent to the back-end compiler and the resulting assembly. Caching when requested is disallowed for now. Signed-off-by: Mary Guillemard Reviewed-by: Boris Brezillon Part-of: --- src/panfrost/vulkan/panvk_shader.h | 3 + src/panfrost/vulkan/panvk_vX_shader.c | 83 +++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/panfrost/vulkan/panvk_shader.h b/src/panfrost/vulkan/panvk_shader.h index fed3cb45434..82684ac5eec 100644 --- a/src/panfrost/vulkan/panvk_shader.h +++ b/src/panfrost/vulkan/panvk_shader.h @@ -129,6 +129,9 @@ struct panvk_shader { struct panvk_priv_mem code_mem; struct panvk_priv_mem rsd; + + const char *nir_str; + const char *asm_str; }; struct panvk_shader_link { diff --git a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c index c913bc497c8..a27b318b14f 100644 --- a/src/panfrost/vulkan/panvk_vX_shader.c +++ b/src/panfrost/vulkan/panvk_vX_shader.c @@ -37,6 +37,7 @@ #include "panvk_shader.h" #include "spirv/nir_spirv.h" +#include "util/memstream.h" #include "util/mesa-sha1.h" #include "util/u_dynarray.h" #include "nir_builder.h" @@ -349,9 +350,6 @@ panvk_compile_nir(struct panvk_device *dev, nir_shader *nir, const bool dump_asm = shader_flags & VK_SHADER_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_MESA; - /* TODO: ASM dumping (VK_KHR_maintenance5) */ - assert(!dump_asm); - struct util_dynarray binary; util_dynarray_init(&binary, NULL); GENX(pan_shader_compile)(nir, compile_input, &binary, &shader->info); @@ -374,6 +372,30 @@ panvk_compile_nir(struct panvk_device *dev, nir_shader *nir, } util_dynarray_fini(&binary); + if (dump_asm) { + shader->nir_str = nir_shader_as_str(nir, NULL); + + char *data = NULL; + size_t disasm_size = 0; + + if (shader->bin_size) { + struct u_memstream mem; + if (u_memstream_open(&mem, &data, &disasm_size)) { + FILE *const stream = u_memstream_get(&mem); + pan_shader_disassemble(stream, shader->bin_ptr, shader->bin_size, + compile_input->gpu_id, false); + u_memstream_close(&mem); + } + } + + char *asm_str = malloc(disasm_size + 1); + memcpy(asm_str, data, disasm_size); + asm_str[disasm_size] = '\0'; + free(data); + + shader->asm_str = asm_str; + } + /* Patch the descriptor count */ shader->info.ubo_count = shader->desc_info.others.count[PANVK_BIFROST_DESC_TABLE_UBO] + @@ -448,6 +470,9 @@ panvk_shader_destroy(struct vk_device *vk_dev, struct vk_shader *vk_shader, struct panvk_shader *shader = container_of(vk_shader, struct panvk_shader, vk); + free((void *)shader->asm_str); + ralloc_free((void *)shader->nir_str); + panvk_pool_free_mem(&dev->mempools.exec, shader->code_mem); panvk_pool_free_mem(&dev->mempools.exec, shader->rsd); panvk_pool_free_mem(&dev->mempools.exec, shader->desc_info.others.map); @@ -680,8 +705,12 @@ panvk_shader_serialize(struct vk_device *vk_dev, struct panvk_shader *shader = container_of(vk_shader, struct panvk_shader, vk); - /* TODO: Disallow serialization with assembly when implemented */ - /* TODO: Implement serialization with assembly */ + /** + * We can't currently cache assembly + * TODO: Implement seriaization with assembly + **/ + if (shader->nir_str != NULL || shader->asm_str != NULL) + return false; blob_write_bytes(blob, &shader->info, sizeof(shader->info)); blob_write_bytes(blob, &shader->local_size, sizeof(shader->local_size)); @@ -751,6 +780,27 @@ panvk_shader_get_executable_statistics( return vk_outarray_status(&out); } +static bool +write_ir_text(VkPipelineExecutableInternalRepresentationKHR *ir, + const char *data) +{ + ir->isText = VK_TRUE; + + size_t data_len = strlen(data) + 1; + + if (ir->pData == NULL) { + ir->dataSize = data_len; + return true; + } + + strncpy(ir->pData, data, ir->dataSize); + if (ir->dataSize < data_len) + return false; + + ir->dataSize = data_len; + return true; +} + static VkResult panvk_shader_get_executable_internal_representations( UNUSED struct vk_device *device, const struct vk_shader *vk_shader, @@ -764,7 +814,28 @@ panvk_shader_get_executable_internal_representations( internal_representation_count); bool incomplete_text = false; - /* TODO: Compiler assembly (VK_KHR_pipeline_executable_properties) */ + if (shader->nir_str != NULL) { + vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, + &out, ir) + { + WRITE_STR(ir->name, "NIR shader"); + WRITE_STR(ir->description, + "NIR shader before sending to the back-end compiler"); + if (!write_ir_text(ir, shader->nir_str)) + incomplete_text = true; + } + } + + if (shader->asm_str != NULL) { + vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, + &out, ir) + { + WRITE_STR(ir->name, "Assembly"); + WRITE_STR(ir->description, "Final Assembly"); + if (!write_ir_text(ir, shader->asm_str)) + incomplete_text = true; + } + } return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out); }