[Mesa-dev] [PATCH] anv: implement basic VK_AMD_shader_info support

Timothy Arceri tarceri at itsqueeze.com
Tue Jun 12 05:07:28 UTC 2018


From: Timothy Arceri <tarceri at localhost.localdomain>

For now this just allows an app to query
VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD which for now only returns
shader-db information. This will allow us to use anv with
vkpipeline-db.

We should add shader disassembly in the future so that RenderDoc
can display it, but that will require a bunch of changes as
currently all the helper functions just fprintf everything to
stderr.
---
 src/intel/vulkan/anv_device.c         |  19 +++-
 src/intel/vulkan/anv_extensions.py    |   1 +
 src/intel/vulkan/anv_pipeline.c       | 129 ++++++++++++++++++++++++--
 src/intel/vulkan/anv_pipeline_cache.c |   1 +
 src/intel/vulkan/anv_private.h        |   5 +
 5 files changed, 147 insertions(+), 8 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index b02e1a2749..f140c6e8e5 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -36,6 +36,7 @@
 #include "util/debug.h"
 #include "util/build_id.h"
 #include "util/mesa-sha1.h"
+#include "util/string_buffer.h"
 #include "vk_util.h"
 #include "common/gen_defines.h"
 
@@ -43,7 +44,15 @@
 
 static void
 compiler_debug_log(void *data, const char *fmt, ...)
-{ }
+{
+   struct _mesa_string_buffer *buf = (struct _mesa_string_buffer *)data;
+   va_list args;
+
+   va_start(args, fmt);
+   _mesa_string_buffer_vprintf(buf, fmt, args);
+   _mesa_string_buffer_printf(buf, "\n");
+   va_end(args);
+}
 
 static void
 compiler_perf_log(void *data, const char *fmt, ...)
@@ -1456,6 +1465,8 @@ VkResult anv_CreateDevice(
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
 
+   bool store_shader_info = false;
+
    struct anv_device_extension_table enabled_extensions = { };
    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
       int idx;
@@ -1471,6 +1482,11 @@ VkResult anv_CreateDevice(
       if (!physical_device->supported_extensions.extensions[idx])
          return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
 
+      if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+                 VK_AMD_SHADER_INFO_EXTENSION_NAME) == 0) {
+         store_shader_info = true;
+      }
+
       enabled_extensions.extensions[idx] = true;
    }
 
@@ -1516,6 +1532,7 @@ VkResult anv_CreateDevice(
    device->chipset_id = physical_device->chipset_id;
    device->no_hw = physical_device->no_hw;
    device->lost = false;
+   device->store_shader_info = store_shader_info;
 
    if (pAllocator)
       device->alloc = *pAllocator;
diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py
index 8160864685..bcff5e848b 100644
--- a/src/intel/vulkan/anv_extensions.py
+++ b/src/intel/vulkan/anv_extensions.py
@@ -68,6 +68,7 @@ MAX_API_VERSION = None # Computed later
 # the those extension strings, then tests dEQP-VK.api.info.instance.extensions
 # and dEQP-VK.api.info.device fail due to the duplicated strings.
 EXTENSIONS = [
+    Extension('VK_AMD_shader_info',                       1, True),
     Extension('VK_ANDROID_native_buffer',                 5, 'ANDROID'),
     Extension('VK_KHR_16bit_storage',                     1, 'device->info.gen >= 8'),
     Extension('VK_KHR_bind_memory2',                      1, True),
diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index 240bde036d..8be349ed19 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 
 #include "util/mesa-sha1.h"
+#include "util/string_buffer.h"
 #include "common/gen_l3_config.h"
 #include "anv_private.h"
 #include "compiler/brw_nir.h"
@@ -81,6 +82,55 @@ void anv_DestroyShaderModule(
    vk_free2(&device->alloc, pAllocator, module);
 }
 
+VkResult anv_GetShaderInfoAMD(
+    VkDevice _device,
+    VkPipeline _pipeline,
+    VkShaderStageFlagBits shaderStage,
+    VkShaderInfoTypeAMD infoType,
+    size_t* pInfoSize,
+    void* pInfo)
+{
+   ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
+
+   gl_shader_stage stage = vk_to_mesa_shader_stage(shaderStage);
+   struct anv_shader_bin *shader = pipeline->shaders[stage];
+   VkResult result = VK_SUCCESS;
+
+   /* Spec doesn't indicate what to do if the stage is invalid, so just
+    * return no info for this.
+    */
+   if (!shader)
+      return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
+
+   switch (infoType) {
+      case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: {
+         /* Need to include the null terminator. */
+         size_t length = strlen(shader->shader_info) + 1;
+
+         if (!pInfo) {
+            *pInfoSize = length;
+         } else {
+            size_t size = *pInfoSize;
+            *pInfoSize = length;
+
+            memcpy(pInfo, shader->shader_info, MIN2(size, length));
+
+            if (size < length)
+               result = VK_INCOMPLETE;
+         }
+         break;
+      }
+      default:
+         /* VK_SHADER_INFO_TYPE_BINARY_AMD and VK_SHADER_INFO_TYPE_STATISTICS_AMD
+          * are unimplemented.
+          */
+         result = VK_ERROR_FEATURE_NOT_PRESENT;
+         break;
+   }
+
+   return result;
+}
+
 #define SPIR_V_MAGIC_NUMBER 0x07230203
 
 static const uint64_t stage_to_debug[] = {
@@ -557,8 +607,12 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
                           nir->info.outputs_written,
                           nir->info.separate_shader);
 
+      struct _mesa_string_buffer *shader_info = NULL;
+      if (pipeline->device->store_shader_info)
+         shader_info = _mesa_string_buffer_create(mem_ctx, 256);
+
       const unsigned *shader_code =
-         brw_compile_vs(compiler, NULL, mem_ctx, &key, &prog_data, nir,
+         brw_compile_vs(compiler, shader_info, mem_ctx, &key, &prog_data, nir,
                         -1, NULL);
       if (shader_code == NULL) {
          ralloc_free(mem_ctx);
@@ -575,6 +629,13 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
+      if (shader_info) {
+         bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1);
+      }
+
       ralloc_free(mem_ctx);
    }
 
@@ -720,12 +781,19 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
       tes_key.inputs_read = tcs_key.outputs_written;
       tes_key.patch_inputs_read = tcs_key.patch_outputs_written;
 
+      struct _mesa_string_buffer *shader_info_tes = NULL;
+      struct _mesa_string_buffer *shader_info_tcs = NULL;
+      if (pipeline->device->store_shader_info) {
+         shader_info_tes = _mesa_string_buffer_create(mem_ctx, 256);
+         shader_info_tcs = _mesa_string_buffer_create(mem_ctx, 256);
+      }
+
       const int shader_time_index = -1;
       const unsigned *shader_code;
 
       shader_code =
-         brw_compile_tcs(compiler, NULL, mem_ctx, &tcs_key, &tcs_prog_data,
-                         tcs_nir, shader_time_index, NULL);
+         brw_compile_tcs(compiler, shader_info_tcs, mem_ctx, &tcs_key,
+                         &tcs_prog_data, tcs_nir, shader_time_index, NULL);
       if (shader_code == NULL) {
          ralloc_free(mem_ctx);
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -744,7 +812,7 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
       }
 
       shader_code =
-         brw_compile_tes(compiler, NULL, mem_ctx, &tes_key,
+         brw_compile_tes(compiler, shader_info_tes, mem_ctx, &tes_key,
                          &tcs_prog_data.base.vue_map, &tes_prog_data, tes_nir,
                          NULL, shader_time_index, NULL);
       if (shader_code == NULL) {
@@ -764,6 +832,20 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
+      if (pipeline->device->store_shader_info) {
+         tcs_bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info_tcs->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(tcs_bin->shader_info, shader_info_tcs->buf,
+                shader_info_tcs->length + 1);
+
+         tes_bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info_tes->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(tes_bin->shader_info, shader_info_tes->buf,
+                shader_info_tes->length + 1);
+      }
+
       ralloc_free(mem_ctx);
    }
 
@@ -826,8 +908,12 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
                           nir->info.outputs_written,
                           nir->info.separate_shader);
 
+      struct _mesa_string_buffer *shader_info = NULL;
+      if (pipeline->device->store_shader_info)
+         shader_info = _mesa_string_buffer_create(mem_ctx, 256);
+
       const unsigned *shader_code =
-         brw_compile_gs(compiler, NULL, mem_ctx, &key, &prog_data, nir,
+         brw_compile_gs(compiler, shader_info, mem_ctx, &key, &prog_data, nir,
                         NULL, -1, NULL);
       if (shader_code == NULL) {
          ralloc_free(mem_ctx);
@@ -845,6 +931,13 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
+      if (shader_info) {
+         bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1);
+      }
+
       ralloc_free(mem_ctx);
    }
 
@@ -977,8 +1070,12 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
 
       anv_fill_binding_table(&prog_data.base, num_rts);
 
+      struct _mesa_string_buffer *shader_info = NULL;
+      if (pipeline->device->store_shader_info)
+         shader_info = _mesa_string_buffer_create(mem_ctx, 256);
+
       const unsigned *shader_code =
-         brw_compile_fs(compiler, NULL, mem_ctx, &key, &prog_data, nir,
+         brw_compile_fs(compiler, shader_info, mem_ctx, &key, &prog_data, nir,
                         NULL, -1, -1, true, false, NULL, NULL);
       if (shader_code == NULL) {
          ralloc_free(mem_ctx);
@@ -995,6 +1092,13 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
+      if (shader_info) {
+         bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1);
+      }
+
       ralloc_free(mem_ctx);
    }
 
@@ -1053,8 +1157,12 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
 
       anv_fill_binding_table(&prog_data.base, 1);
 
+      struct _mesa_string_buffer *shader_info = NULL;
+      if (pipeline->device->store_shader_info)
+         shader_info = _mesa_string_buffer_create(mem_ctx, 256);
+
       const unsigned *shader_code =
-         brw_compile_cs(compiler, NULL, mem_ctx, &key, &prog_data, nir,
+         brw_compile_cs(compiler, shader_info, mem_ctx, &key, &prog_data, nir,
                         -1, NULL);
       if (shader_code == NULL) {
          ralloc_free(mem_ctx);
@@ -1071,6 +1179,13 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       }
 
+      if (shader_info) {
+         bin->shader_info =
+            vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8,
+                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+         memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1);
+      }
+
       ralloc_free(mem_ctx);
    }
 
diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c
index 82551e9f81..9865eaa84e 100644
--- a/src/intel/vulkan/anv_pipeline_cache.c
+++ b/src/intel/vulkan/anv_pipeline_cache.c
@@ -89,6 +89,7 @@ anv_shader_bin_destroy(struct anv_device *device,
 {
    assert(shader->ref_cnt == 0);
    anv_state_pool_free(&device->instruction_state_pool, shader->kernel);
+   vk_free(&device->alloc, shader->shader_info);
    vk_free(&device->alloc, shader);
 }
 
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index b47420f89e..4d675a64ec 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -980,6 +980,8 @@ struct anv_device {
     pthread_mutex_t                             mutex;
     pthread_cond_t                              queue_submit;
     bool                                        lost;
+
+    bool                                        store_shader_info;
 };
 
 static inline struct anv_state_pool *
@@ -2296,6 +2298,9 @@ struct anv_shader_bin {
    uint32_t prog_data_size;
 
    struct anv_pipeline_bind_map bind_map;
+
+   /* Disassembly/shader information use by VK_AMD_shader_info */
+   char *shader_info;
 };
 
 struct anv_shader_bin *
-- 
2.17.1



More information about the mesa-dev mailing list