anv: Use a dynamic array for storing executables in pipeline
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Tue, 3 Mar 2020 18:19:15 +0000 (10:19 -0800)
committerCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Thu, 12 Mar 2020 20:18:54 +0000 (13:18 -0700)
Avoids waste for pipelines that don't use all the shaders, and is
flexible enough to cover cases where there are multiple variants per
shader (e.g. SIMD8/16/32 for fragment shader).

Even though we could pre-calculate the exact size of the array, this
is not a critical path so it is worth preventing the bug that will
likely happen when new variants are added but not accounted for.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4040>

src/intel/vulkan/anv_pipeline.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/genX_pipeline.c

index eeeb9f324ed5d89bb180f20ea36b7f5856c716a6..9f14fb88f821d7b2727cd0e570f13af41ab743ee 100644 (file)
@@ -1051,13 +1051,14 @@ anv_pipeline_add_executable(struct anv_pipeline *pipeline,
       free(stream_data);
    }
 
-   pipeline->executables[pipeline->num_executables++] =
-      (struct anv_pipeline_executable) {
-         .stage = stage->stage,
-         .stats = *stats,
-         .nir = nir,
-         .disasm = disasm,
-      };
+   const struct anv_pipeline_executable exe = {
+      .stage = stage->stage,
+      .stats = *stats,
+      .nir = nir,
+      .disasm = disasm,
+   };
+   util_dynarray_append(&pipeline->executables,
+                        struct anv_pipeline_executable, exe);
 }
 
 static void
@@ -1873,7 +1874,8 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
     * of various prog_data pointers.  Make them NULL by default.
     */
    memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-   pipeline->num_executables = 0;
+
+   util_dynarray_init(&pipeline->executables, pipeline->mem_ctx);
 
    result = anv_pipeline_compile_graphics(pipeline, cache, pCreateInfo);
    if (result != VK_SUCCESS) {
@@ -1976,12 +1978,12 @@ VkResult anv_GetPipelineExecutablePropertiesKHR(
    ANV_FROM_HANDLE(anv_pipeline, pipeline, pPipelineInfo->pipeline);
    VK_OUTARRAY_MAKE(out, pProperties, pExecutableCount);
 
-   for (uint32_t i = 0; i < pipeline->num_executables; i++) {
+   util_dynarray_foreach (&pipeline->executables, struct anv_pipeline_executable, exe) {
       vk_outarray_append(&out, props) {
-         gl_shader_stage stage = pipeline->executables[i].stage;
+         gl_shader_stage stage = exe->stage;
          props->stages = mesa_to_vk_shader_stage(stage);
 
-         unsigned simd_width = pipeline->executables[i].stats.dispatch_width;
+         unsigned simd_width = exe->stats.dispatch_width;
          if (stage == MESA_SHADER_FRAGMENT) {
             WRITE_STR(props->name, "%s%d %s",
                       simd_width ? "SIMD" : "vec",
@@ -2005,6 +2007,15 @@ VkResult anv_GetPipelineExecutablePropertiesKHR(
    return vk_outarray_status(&out);
 }
 
+static const struct anv_pipeline_executable *
+anv_pipeline_get_executable(struct anv_pipeline *pipeline, uint32_t index)
+{
+   assert(index < util_dynarray_num_elements(&pipeline->executables,
+                                             struct anv_pipeline_executable));
+   return util_dynarray_element(
+      &pipeline->executables, struct anv_pipeline_executable, index);
+}
+
 VkResult anv_GetPipelineExecutableStatisticsKHR(
     VkDevice                                    device,
     const VkPipelineExecutableInfoKHR*          pExecutableInfo,
@@ -2014,9 +2025,8 @@ VkResult anv_GetPipelineExecutableStatisticsKHR(
    ANV_FROM_HANDLE(anv_pipeline, pipeline, pExecutableInfo->pipeline);
    VK_OUTARRAY_MAKE(out, pStatistics, pStatisticCount);
 
-   assert(pExecutableInfo->executableIndex < pipeline->num_executables);
    const struct anv_pipeline_executable *exe =
-      &pipeline->executables[pExecutableInfo->executableIndex];
+      anv_pipeline_get_executable(pipeline, pExecutableInfo->executableIndex);
    const struct brw_stage_prog_data *prog_data =
       pipeline->shaders[exe->stage]->prog_data;
 
@@ -2127,9 +2137,8 @@ VkResult anv_GetPipelineExecutableInternalRepresentationsKHR(
                     pInternalRepresentationCount);
    bool incomplete_text = false;
 
-   assert(pExecutableInfo->executableIndex < pipeline->num_executables);
    const struct anv_pipeline_executable *exe =
-      &pipeline->executables[pExecutableInfo->executableIndex];
+      anv_pipeline_get_executable(pipeline, pExecutableInfo->executableIndex);
 
    if (exe->nir) {
       vk_outarray_append(&out, ir) {
index cdb2a725a91ba93a6b624c367189589e054f0138..3607b7d4fcd80f29722b1701fa3c5e875bd1a620 100644 (file)
@@ -3145,9 +3145,6 @@ anv_shader_bin_unref(struct anv_device *device, struct anv_shader_bin *shader)
       anv_shader_bin_destroy(device, shader);
 }
 
-/* 5 possible simultaneous shader stages and FS may have up to 3 binaries */
-#define MAX_PIPELINE_EXECUTABLES 7
-
 struct anv_pipeline_executable {
    gl_shader_stage stage;
 
@@ -3178,8 +3175,7 @@ struct anv_pipeline {
 
    struct anv_shader_bin *                      shaders[MESA_SHADER_STAGES];
 
-   uint32_t                                     num_executables;
-   struct anv_pipeline_executable               executables[MAX_PIPELINE_EXECUTABLES];
+   struct util_dynarray                         executables;
 
    const struct gen_l3_config *                 l3_config;
 
index c5c5e73874ec8128a8707837872411d8117cb76b..5b692a7e8130fad26172543584a9fa4500e917bc 100644 (file)
@@ -2256,7 +2256,8 @@ compute_pipeline_create(
     * of various prog_data pointers.  Make them NULL by default.
     */
    memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
-   pipeline->num_executables = 0;
+
+   util_dynarray_init(&pipeline->executables, pipeline->mem_ctx);
 
    assert(pCreateInfo->stage.stage == VK_SHADER_STAGE_COMPUTE_BIT);
    pipeline->active_stages |= VK_SHADER_STAGE_COMPUTE_BIT;