radv: dump shader stats with VK_KHR_pipeline_executable_properties
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 20 Aug 2020 14:03:36 +0000 (16:03 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 31 Aug 2020 07:42:25 +0000 (09:42 +0200)
Instead of duplicating shader statistics in two different parts
in the driver. This also now reports the LDS size in bytes instead
of blocks with VK_AMD_shader_info.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6406>

src/amd/vulkan/radv_debug.c
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_shader.c
src/amd/vulkan/radv_shader.h

index 0c9ed2752fb23c3bf27ea86b4c98ba0e4b985bba..d50480aa47ffbace3cc6ef4a8b0abcf0e8786d06 100644 (file)
@@ -444,7 +444,7 @@ radv_dump_shader(struct radv_pipeline *pipeline,
                shader->ir_string);
        fprintf(f, "DISASM:\n%s\n", shader->disasm_string);
 
-       radv_shader_dump_stats(pipeline->device, shader, stage, f);
+       radv_dump_shader_stats(pipeline->device, pipeline, stage, f);
 }
 
 static void
index 33d594f6c48cfd93e15e93f2a90bd2be4affb4f7..faae8252c93bd6a491e6a662819f11ef452aaff9 100644 (file)
@@ -3104,10 +3104,9 @@ VkResult radv_create_shaders(struct radv_pipeline *pipeline,
                if (nir[i]) {
                        ralloc_free(nir[i]);
 
-                       if (radv_can_dump_shader_stats(device, modules[i]))
-                               radv_shader_dump_stats(device,
-                                                      pipeline->shaders[i],
-                                                      i, stderr);
+                       if (radv_can_dump_shader_stats(device, modules[i])) {
+                               radv_dump_shader_stats(device, pipeline, i, stderr);
+                       }
                }
        }
 
index 613690809977adf10cb3246da8a132aa306f8a54..b462393b11803d215bf9ffd94aae7e9ae178f806 100644 (file)
@@ -47,8 +47,6 @@
 
 #include "aco_interface.h"
 
-#include "util/string_buffer.h"
-
 static const struct nir_shader_compiler_options nir_options_llvm = {
        .vertex_id_zero_based = true,
        .lower_scmp = true,
@@ -1507,66 +1505,6 @@ radv_get_max_waves(struct radv_device *device,
        return max_simd_waves;
 }
 
-static void
-generate_shader_stats(struct radv_device *device,
-                     struct radv_shader_variant *variant,
-                     gl_shader_stage stage,
-                     struct _mesa_string_buffer *buf)
-{
-       struct ac_shader_config *conf = &variant->config;
-       unsigned max_simd_waves = radv_get_max_waves(device, variant, stage);
-
-       if (stage == MESA_SHADER_FRAGMENT) {
-               _mesa_string_buffer_printf(buf, "*** SHADER CONFIG ***\n"
-                                          "SPI_PS_INPUT_ADDR = 0x%04x\n"
-                                          "SPI_PS_INPUT_ENA  = 0x%04x\n",
-                                          conf->spi_ps_input_addr, conf->spi_ps_input_ena);
-       }
-
-       _mesa_string_buffer_printf(buf, "*** SHADER STATS ***\n"
-                                  "SGPRS: %d\n"
-                                  "VGPRS: %d\n"
-                                  "Spilled SGPRs: %d\n"
-                                  "Spilled VGPRs: %d\n"
-                                  "PrivMem VGPRS: %d\n"
-                                  "Code Size: %d bytes\n"
-                                  "LDS: %d blocks\n"
-                                  "Scratch: %d bytes per wave\n"
-                                  "Max Waves: %d\n",
-                                  conf->num_sgprs, conf->num_vgprs,
-                                  conf->spilled_sgprs, conf->spilled_vgprs,
-                                  variant->info.private_mem_vgprs, variant->exec_size,
-                                  conf->lds_size, conf->scratch_bytes_per_wave,
-                                  max_simd_waves);
-
-       if (variant->statistics) {
-               _mesa_string_buffer_printf(buf, "*** COMPILER STATS ***\n");
-               for (unsigned i = 0; i < variant->statistics->count; i++) {
-                       struct radv_compiler_statistic_info *info = &variant->statistics->infos[i];
-                       uint32_t value = variant->statistics->values[i];
-                       _mesa_string_buffer_printf(buf, "%s: %lu\n", info->name, value);
-               }
-       }
-
-       _mesa_string_buffer_printf(buf, "********************\n\n\n");
-}
-
-void
-radv_shader_dump_stats(struct radv_device *device,
-                      struct radv_shader_variant *variant,
-                      gl_shader_stage stage,
-                      FILE *file)
-{
-       struct _mesa_string_buffer *buf = _mesa_string_buffer_create(NULL, 256);
-
-       generate_shader_stats(device, variant, stage, buf);
-
-       fprintf(file, "\n%s:\n", radv_get_shader_name(&variant->info, stage));
-       fprintf(file, "%s", buf->buf);
-
-       _mesa_string_buffer_destroy(buf);
-}
-
 VkResult
 radv_GetShaderInfoAMD(VkDevice _device,
                      VkPipeline _pipeline,
@@ -1579,7 +1517,6 @@ radv_GetShaderInfoAMD(VkDevice _device,
        RADV_FROM_HANDLE(radv_pipeline, pipeline, _pipeline);
        gl_shader_stage stage = vk_to_mesa_shader_stage(shaderStage);
        struct radv_shader_variant *variant = pipeline->shaders[stage];
-       struct _mesa_string_buffer *buf;
        VkResult result = VK_SUCCESS;
 
        /* Spec doesn't indicate what to do if the stage is invalid, so just
@@ -1631,16 +1568,19 @@ radv_GetShaderInfoAMD(VkDevice _device,
                }
 
                break;
-       case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD:
-               buf = _mesa_string_buffer_create(NULL, 1024);
+       case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: {
+               char *out;
+               size_t outsize;
+               FILE *memf = open_memstream(&out, &outsize);
 
-               _mesa_string_buffer_printf(buf, "%s:\n", radv_get_shader_name(&variant->info, stage));
-               _mesa_string_buffer_printf(buf, "%s\n\n", variant->ir_string);
-               _mesa_string_buffer_printf(buf, "%s\n\n", variant->disasm_string);
-               generate_shader_stats(device, variant, stage, buf);
+               fprintf(memf, "%s:\n", radv_get_shader_name(&variant->info, stage));
+               fprintf(memf, "%s\n\n", variant->ir_string);
+               fprintf(memf, "%s\n\n", variant->disasm_string);
+               radv_dump_shader_stats(device, pipeline, stage, memf);
+               fclose(memf);
 
                /* Need to include the null terminator. */
-               size_t length = buf->length + 1;
+               size_t length = outsize + 1;
 
                if (!pInfo) {
                        *pInfoSize = length;
@@ -1648,14 +1588,15 @@ radv_GetShaderInfoAMD(VkDevice _device,
                        size_t size = *pInfoSize;
                        *pInfoSize = length;
 
-                       memcpy(pInfo, buf->buf, MIN2(size, length));
+                       memcpy(pInfo, out, MIN2(size, length));
 
                        if (size < length)
                                result = VK_INCOMPLETE;
                }
 
-               _mesa_string_buffer_destroy(buf);
+               free(out);
                break;
+       }
        default:
                /* VK_SHADER_INFO_TYPE_BINARY_AMD unimplemented for now. */
                result = VK_ERROR_FEATURE_NOT_PRESENT;
@@ -1664,3 +1605,100 @@ radv_GetShaderInfoAMD(VkDevice _device,
 
        return result;
 }
+
+VkResult
+radv_dump_shader_stats(struct radv_device *device,
+                      struct radv_pipeline *pipeline,
+                      gl_shader_stage stage, FILE *output)
+{
+       struct radv_shader_variant *shader = pipeline->shaders[stage];
+       VkPipelineExecutablePropertiesKHR *props = NULL;
+       uint32_t prop_count = 0;
+       VkResult result;
+
+       VkPipelineInfoKHR pipeline_info = {};
+       pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
+       pipeline_info.pipeline = radv_pipeline_to_handle(pipeline);
+
+       result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device),
+                                                        &pipeline_info,
+                                                        &prop_count, NULL);
+       if (result != VK_SUCCESS)
+               return result;
+
+       props = calloc(prop_count, sizeof(*props));
+       if (!props)
+               return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+       result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device),
+                                                        &pipeline_info,
+                                                        &prop_count, props);
+       if (result != VK_SUCCESS)
+               goto fail;
+
+       for (unsigned i = 0; i < prop_count; i++) {
+               if (!(props[i].stages & mesa_to_vk_shader_stage(stage)))
+                       continue;
+
+               VkPipelineExecutableStatisticKHR *stats = NULL;
+               uint32_t stat_count = 0;
+               VkResult result;
+
+               VkPipelineExecutableInfoKHR exec_info = {};
+               exec_info.pipeline = radv_pipeline_to_handle(pipeline);
+               exec_info.executableIndex = i;
+
+               result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device),
+                                                                &exec_info,
+                                                                &stat_count, NULL);
+               if (result != VK_SUCCESS)
+                       goto fail;
+
+               stats = calloc(stat_count, sizeof(*stats));
+               if (!stats) {
+                       result = VK_ERROR_OUT_OF_HOST_MEMORY;
+                       goto fail;
+               }
+
+               result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device),
+                                                                &exec_info,
+                                                                &stat_count, stats);
+               if (result != VK_SUCCESS) {
+                       free(stats);
+                       goto fail;
+               }
+
+               fprintf(output, "\n%s:\n",
+                       radv_get_shader_name(&shader->info, stage));
+               fprintf(output, "*** SHADER STATS ***\n");
+
+               for (unsigned i = 0; i < stat_count; i++) {
+                       fprintf(output, "%s: ", stats[i].name);
+                       switch (stats[i].format) {
+                       case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
+                               fprintf(output, "%s", stats[i].value.b32 == VK_TRUE ? "true" : "false");
+                               break;
+                       case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
+                               fprintf(output, "%"PRIi64, stats[i].value.i64);
+                               break;
+                       case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
+                               fprintf(output, "%"PRIu64, stats[i].value.u64);
+                               break;
+                       case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
+                               fprintf(output, "%f", stats[i].value.f64);
+                               break;
+                       default:
+                               unreachable("Invalid pipeline statistic format");
+                       }
+                       fprintf(output, "\n");
+               }
+
+               fprintf(output, "********************\n\n\n");
+
+               free(stats);
+       }
+
+fail:
+       free(props);
+       return result;
+}
index 1638614091cebe822d3c368fb46ede8f231aa638..81f620140092c2006505f6165ec7aa36d00545fb 100644 (file)
@@ -510,12 +510,6 @@ const char *
 radv_get_shader_name(struct radv_shader_info *info,
                     gl_shader_stage stage);
 
-void
-radv_shader_dump_stats(struct radv_device *device,
-                      struct radv_shader_variant *variant,
-                      gl_shader_stage stage,
-                      FILE *file);
-
 bool
 radv_can_dump_shader(struct radv_device *device,
                     struct radv_shader_module *module,
@@ -525,6 +519,11 @@ bool
 radv_can_dump_shader_stats(struct radv_device *device,
                           struct radv_shader_module *module);
 
+VkResult
+radv_dump_shader_stats(struct radv_device *device,
+                      struct radv_pipeline *pipeline,
+                      gl_shader_stage stage, FILE *output);
+
 static inline unsigned
 shader_io_get_unique_index(gl_varying_slot slot)
 {