Module: Mesa
Branch: main
Commit: 7e00380445c8d300defb0e697705222c3de5835b
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=7e00380445c8d300defb0e697705222c3de5835b

Author: Faith Ekstrand <[email protected]>
Date:   Thu Nov 16 15:41:31 2023 -0600

nvk: Implement VK_KHR_pipeline_executable_properties

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9621
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26241>

---

 src/nouveau/vulkan/nvk_compute_pipeline.c  |   5 +-
 src/nouveau/vulkan/nvk_graphics_pipeline.c |   5 +-
 src/nouveau/vulkan/nvk_physical_device.c   |   4 +
 src/nouveau/vulkan/nvk_pipeline.c          | 138 +++++++++++++++++++++++++++++
 src/nouveau/vulkan/nvk_shader.c            |  15 +++-
 src/nouveau/vulkan/nvk_shader.h            |   1 +
 6 files changed, 162 insertions(+), 6 deletions(-)

diff --git a/src/nouveau/vulkan/nvk_compute_pipeline.c 
b/src/nouveau/vulkan/nvk_compute_pipeline.c
index f51cddea38b..21d13fa5ef4 100644
--- a/src/nouveau/vulkan/nvk_compute_pipeline.c
+++ b/src/nouveau/vulkan/nvk_compute_pipeline.c
@@ -176,6 +176,9 @@ nvk_compute_pipeline_create(struct nvk_device *dev,
 
    assert(pCreateInfo->stage.stage == VK_SHADER_STAGE_COMPUTE_BIT);
 
+   VkPipelineCreateFlags2KHR pipeline_flags =
+      vk_compute_pipeline_create_flags(pCreateInfo);
+
    struct vk_pipeline_robustness_state robustness;
    vk_pipeline_robustness_state_fill(&dev->vk, &robustness,
                                      pCreateInfo->pNext,
@@ -189,7 +192,7 @@ nvk_compute_pipeline_create(struct nvk_device *dev,
 
    nvk_lower_nir(dev, nir, &robustness, false, pipeline_layout);
 
-   result = nvk_compile_nir(pdev, nir, NULL,
+   result = nvk_compile_nir(pdev, nir, pipeline_flags, NULL,
                             &pipeline->base.shaders[MESA_SHADER_COMPUTE]);
    ralloc_free(nir);
    if (result != VK_SUCCESS)
diff --git a/src/nouveau/vulkan/nvk_graphics_pipeline.c 
b/src/nouveau/vulkan/nvk_graphics_pipeline.c
index bc734c77564..35bddedd548 100644
--- a/src/nouveau/vulkan/nvk_graphics_pipeline.c
+++ b/src/nouveau/vulkan/nvk_graphics_pipeline.c
@@ -314,6 +314,9 @@ nvk_graphics_pipeline_create(struct nvk_device *dev,
    if (pipeline == NULL)
       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
 
+   VkPipelineCreateFlags2KHR pipeline_flags =
+      vk_graphics_pipeline_create_flags(pCreateInfo);
+
    struct vk_graphics_pipeline_all_state all;
    struct vk_graphics_pipeline_state state = {};
    result = vk_graphics_pipeline_state_fill(&dev->vk, &state, pCreateInfo,
@@ -358,7 +361,7 @@ nvk_graphics_pipeline_create(struct nvk_device *dev,
          fs_key = &fs_key_tmp;
       }
 
-      result = nvk_compile_nir(pdev, nir[stage], fs_key,
+      result = nvk_compile_nir(pdev, nir[stage], pipeline_flags, fs_key,
                                &pipeline->base.shaders[stage]);
       ralloc_free(nir[stage]);
       if (result != VK_SUCCESS)
diff --git a/src/nouveau/vulkan/nvk_physical_device.c 
b/src/nouveau/vulkan/nvk_physical_device.c
index 94cde20309c..86252246283 100644
--- a/src/nouveau/vulkan/nvk_physical_device.c
+++ b/src/nouveau/vulkan/nvk_physical_device.c
@@ -73,6 +73,7 @@ nvk_get_device_extensions(const struct nv_device_info *info,
       .KHR_maintenance4 = true,
       .KHR_map_memory2 = true,
       .KHR_multiview = true,
+      .KHR_pipeline_executable_properties = true,
       .KHR_push_descriptor = true,
       .KHR_relaxed_block_layout = true,
       .KHR_sampler_mirror_clamp_to_edge = true,
@@ -251,6 +252,9 @@ nvk_get_device_features(const struct nv_device_info *info,
       .dynamicRendering = true,
       .maintenance4 = true,
 
+      /* VK_KHR_pipeline_executable_properties */
+      .pipelineExecutableInfo = true,
+
       /* VK_KHR_shader_clock */
       .shaderSubgroupClock = true,
       .shaderDeviceClock = true,
diff --git a/src/nouveau/vulkan/nvk_pipeline.c 
b/src/nouveau/vulkan/nvk_pipeline.c
index 36a71c4fb56..a4ee7f8b37f 100644
--- a/src/nouveau/vulkan/nvk_pipeline.c
+++ b/src/nouveau/vulkan/nvk_pipeline.c
@@ -112,3 +112,141 @@ nvk_DestroyPipeline(VkDevice _device, VkPipeline 
_pipeline,
 
    nvk_pipeline_free(dev, pipeline, pAllocator);
 }
+
+#define WRITE_STR(field, ...) ({                               \
+   memset(field, 0, sizeof(field));                            \
+   UNUSED int i = snprintf(field, sizeof(field), __VA_ARGS__); \
+   assert(i > 0 && i < sizeof(field));                         \
+})
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_GetPipelineExecutablePropertiesKHR(
+   VkDevice device,
+   const VkPipelineInfoKHR *pPipelineInfo,
+   uint32_t *pExecutableCount,
+   VkPipelineExecutablePropertiesKHR *pProperties)
+{
+   VK_FROM_HANDLE(nvk_pipeline, pipeline, pPipelineInfo->pipeline);
+   VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutablePropertiesKHR, out,
+                          pProperties, pExecutableCount);
+
+   for (gl_shader_stage stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+      if (pipeline->shaders[stage].code_size == 0)
+         continue;
+
+      vk_outarray_append_typed(VkPipelineExecutablePropertiesKHR, &out, props) 
{
+         props->stages = mesa_to_vk_shader_stage(stage);
+         props->subgroupSize = 32;
+         WRITE_STR(props->name, "%s", _mesa_shader_stage_to_string(stage));
+         WRITE_STR(props->description, "%s shader",
+                   _mesa_shader_stage_to_string(stage));
+      }
+   }
+
+   return vk_outarray_status(&out);
+}
+
+static struct nvk_shader *
+shader_for_exe_idx(struct nvk_pipeline *pipeline, uint32_t idx)
+{
+   for (gl_shader_stage stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+      if (pipeline->shaders[stage].code_size == 0)
+         continue;
+
+      if (idx == 0)
+         return &pipeline->shaders[stage];
+
+      idx--;
+   }
+
+   return NULL;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_GetPipelineExecutableStatisticsKHR(
+    VkDevice device,
+    const VkPipelineExecutableInfoKHR *pExecutableInfo,
+    uint32_t *pStatisticCount,
+    VkPipelineExecutableStatisticKHR *pStatistics)
+{
+   VK_FROM_HANDLE(nvk_pipeline, pipeline, pExecutableInfo->pipeline);
+   VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableStatisticKHR, out,
+                          pStatistics, pStatisticCount);
+
+   struct nvk_shader *shader =
+      shader_for_exe_idx(pipeline, pExecutableInfo->executableIndex);
+
+   vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
+      WRITE_STR(stat->name, "Code Size");
+      WRITE_STR(stat->description,
+                "Size of the compiled shader binary, in bytes");
+      stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
+      stat->value.u64 = shader->code_size;
+   }
+
+   vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
+      WRITE_STR(stat->name, "Number of GPRs");
+      WRITE_STR(stat->description, "Number of GPRs used by this pipeline");
+      stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
+      stat->value.u64 = shader->info.num_gprs;
+   }
+
+   vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
+      WRITE_STR(stat->name, "SLM Size");
+      WRITE_STR(stat->description,
+                "Size of shader local (scratch) memory, in bytes");
+      stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
+      stat->value.u64 = shader->info.slm_size;
+   }
+
+   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;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_GetPipelineExecutableInternalRepresentationsKHR(
+    VkDevice device,
+    const VkPipelineExecutableInfoKHR *pExecutableInfo,
+    uint32_t *pInternalRepresentationCount,
+    VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations)
+{
+   VK_FROM_HANDLE(nvk_pipeline, pipeline, pExecutableInfo->pipeline);
+   VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableInternalRepresentationKHR, out,
+                          pInternalRepresentations,
+                          pInternalRepresentationCount);
+   bool incomplete_text = false;
+
+   struct nvk_shader *shader =
+      shader_for_exe_idx(pipeline, pExecutableInfo->executableIndex);
+
+   if (shader->nak != NULL && shader->nak->asm_str != NULL) {
+      vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, 
&out, ir) {
+         WRITE_STR(ir->name, "NAK assembly");
+         WRITE_STR(ir->description, "NAK assembly");
+         if (!write_ir_text(ir, shader->nak->asm_str))
+            incomplete_text = true;
+      }
+   }
+
+   return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out);
+}
diff --git a/src/nouveau/vulkan/nvk_shader.c b/src/nouveau/vulkan/nvk_shader.c
index b82a5572102..47435bd5523 100644
--- a/src/nouveau/vulkan/nvk_shader.c
+++ b/src/nouveau/vulkan/nvk_shader.c
@@ -395,10 +395,14 @@ nvk_shader_dump(struct nvk_shader *shader)
 static VkResult
 nvk_compile_nir_with_nak(struct nvk_physical_device *pdev,
                          nir_shader *nir,
+                         VkPipelineCreateFlagBits2KHR pipeline_flags,
                          const struct nak_fs_key *fs_key,
                          struct nvk_shader *shader)
 {
-   shader->nak = nak_compile_shader(nir, false, pdev->nak, fs_key);
+   const bool dump_asm =
+      pipeline_flags & 
VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
+
+   shader->nak = nak_compile_shader(nir, dump_asm, pdev->nak, fs_key);
    shader->info = shader->nak->info;
    shader->code_ptr = shader->nak->code;
    shader->code_size = shader->nak->code_size;
@@ -408,13 +412,16 @@ nvk_compile_nir_with_nak(struct nvk_physical_device *pdev,
 
 VkResult
 nvk_compile_nir(struct nvk_physical_device *pdev, nir_shader *nir,
+                VkPipelineCreateFlagBits2KHR pipeline_flags,
                 const struct nak_fs_key *fs_key,
                 struct nvk_shader *shader)
 {
-   if (use_nak(pdev, nir->info.stage))
-      return nvk_compile_nir_with_nak(pdev, nir, fs_key, shader);
-   else
+   if (use_nak(pdev, nir->info.stage)) {
+      return nvk_compile_nir_with_nak(pdev, nir, pipeline_flags,
+                                      fs_key, shader);
+   } else {
       return nvk_cg_compile_nir(pdev, nir, fs_key, shader);
+   }
 }
 
 VkResult
diff --git a/src/nouveau/vulkan/nvk_shader.h b/src/nouveau/vulkan/nvk_shader.h
index 9e7d2430a3a..7ce8187236c 100644
--- a/src/nouveau/vulkan/nvk_shader.h
+++ b/src/nouveau/vulkan/nvk_shader.h
@@ -90,6 +90,7 @@ nvk_lower_nir(struct nvk_device *dev, nir_shader *nir,
 
 VkResult
 nvk_compile_nir(struct nvk_physical_device *dev, nir_shader *nir,
+                VkPipelineCreateFlagBits2KHR pipeline_flags,
                 const struct nak_fs_key *fs_key,
                 struct nvk_shader *shader);
 

Reply via email to