[Mesa-dev] [PATCH v3 08/12] anv: add descriptor support for multiplanar image/sampler

Lionel Landwerlin lionel.g.landwerlin at intel.com
Wed Oct 4 17:34:53 UTC 2017


v2: Drop a memset by using zalloc (Jason)
    Decouple vulkan descriptors from the underlying binding table
    (Jason)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
---
 src/intel/vulkan/anv_descriptor_set.c            | 24 ++++++++-
 src/intel/vulkan/anv_nir_apply_pipeline_layout.c | 66 ++++++++++++++----------
 src/intel/vulkan/anv_private.h                   | 22 ++++++++
 src/intel/vulkan/genX_cmd_buffer.c               | 17 +++---
 src/intel/vulkan/genX_state.c                    |  2 +
 5 files changed, 97 insertions(+), 34 deletions(-)

diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_descriptor_set.c
index 84077982307..704693e227f 100644
--- a/src/intel/vulkan/anv_descriptor_set.c
+++ b/src/intel/vulkan/anv_descriptor_set.c
@@ -35,6 +35,21 @@
  * Descriptor set layouts.
  */
 
+static uint32_t
+layout_binding_get_hw_binding_size(const VkDescriptorSetLayoutBinding *binding)
+{
+   if (binding->pImmutableSamplers == NULL)
+      return binding->descriptorCount;
+
+   uint32_t immutable_sampler_count = 0;
+   for (uint32_t i = 0; i < binding->descriptorCount; i++) {
+      ANV_FROM_HANDLE(anv_sampler, sampler, binding->pImmutableSamplers[i]);
+      immutable_sampler_count += sampler->n_planes;
+   }
+
+   return immutable_sampler_count;
+}
+
 VkResult anv_CreateDescriptorSetLayout(
     VkDevice                                    _device,
     const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
@@ -75,6 +90,7 @@ VkResult anv_CreateDescriptorSetLayout(
 
       set_layout->binding[b].array_size = 0;
       set_layout->binding[b].immutable_samplers = NULL;
+      set_layout->binding[b].hw_binding_size = 0;
    }
 
    /* Initialize all samplers to 0 */
@@ -108,8 +124,13 @@ VkResult anv_CreateDescriptorSetLayout(
       set_layout->binding[b].type = binding->descriptorType;
 #endif
       set_layout->binding[b].array_size = binding->descriptorCount;
+      set_layout->binding[b].hw_binding_size =
+         layout_binding_get_hw_binding_size(binding);
       set_layout->binding[b].descriptor_index = set_layout->size;
+      set_layout->binding[b].hw_binding_index = set_layout->hw_size;
+
       set_layout->size += binding->descriptorCount;
+      set_layout->hw_size += set_layout->binding[b].hw_binding_size;
 
       switch (binding->descriptorType) {
       case VK_DESCRIPTOR_TYPE_SAMPLER:
@@ -323,6 +344,8 @@ VkResult anv_CreateDescriptorPool(
       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
          buffer_count += pCreateInfo->pPoolSizes[i].descriptorCount;
+         /* Fallthrough */
+
       default:
          descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;
          break;
@@ -612,7 +635,6 @@ anv_descriptor_set_write_image_view(struct anv_descriptor_set *set,
    sampler = bind_layout->immutable_samplers ?
              bind_layout->immutable_samplers[element] :
              sampler;
-
    *desc = (struct anv_descriptor) {
       .type = type,
       .layout = info->imageLayout,
diff --git a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
index 67bcf5e29ef..428cfdf42d1 100644
--- a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
+++ b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c
@@ -130,7 +130,7 @@ lower_res_index_intrinsic(nir_intrinsic_instr *intrin,
 
 static void
 lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref,
-                unsigned *const_index, unsigned array_size,
+                unsigned *const_index, unsigned hw_binding_size,
                 nir_tex_src_type src_type,
                 struct apply_pipeline_layout_state *state)
 {
@@ -146,7 +146,7 @@ lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref,
                         nir_ssa_for_src(b, deref_array->indirect, 1));
 
          if (state->add_bounds_checks)
-            index = nir_umin(b, index, nir_imm_int(b, array_size - 1));
+            index = nir_umin(b, index, nir_imm_int(b, hw_binding_size - 1));
 
          nir_tex_src *new_srcs = rzalloc_array(tex, nir_tex_src,
                                                tex->num_srcs + 1);
@@ -167,7 +167,7 @@ lower_tex_deref(nir_tex_instr *tex, nir_deref_var *deref,
                                nir_src_for_ssa(index));
          tex->num_srcs++;
       } else {
-         *const_index += MIN2(deref_array->base_offset, array_size - 1);
+         *const_index += MIN2(deref_array->base_offset, hw_binding_size - 1);
       }
    }
 }
@@ -196,19 +196,18 @@ lower_tex(nir_tex_instr *tex, struct apply_pipeline_layout_state *state)
 
    unsigned set = tex->texture->var->data.descriptor_set;
    unsigned binding = tex->texture->var->data.binding;
-   unsigned array_size =
-      state->layout->set[set].layout->binding[binding].array_size;
+   unsigned hw_binding_size =
+      state->layout->set[set].layout->binding[binding].hw_binding_size;
    tex->texture_index = state->set[set].surface_offsets[binding];
-   lower_tex_deref(tex, tex->texture, &tex->texture_index, array_size,
+   lower_tex_deref(tex, tex->texture, &tex->texture_index, hw_binding_size,
                    nir_tex_src_texture_offset, state);
 
    if (tex->sampler) {
       unsigned set = tex->sampler->var->data.descriptor_set;
       unsigned binding = tex->sampler->var->data.binding;
-      unsigned array_size =
-         state->layout->set[set].layout->binding[binding].array_size;
-      tex->sampler_index = state->set[set].sampler_offsets[binding];
-      lower_tex_deref(tex, tex->sampler, &tex->sampler_index, array_size,
+      unsigned hw_binding_size =
+         state->layout->set[set].layout->binding[binding].hw_binding_size;
+      lower_tex_deref(tex, tex->sampler, &tex->sampler_index, hw_binding_size,
                       nir_tex_src_sampler_offset, state);
    }
 
@@ -300,9 +299,9 @@ anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline,
       BITSET_FOREACH_SET(b, _tmp, state.set[set].used,
                          set_layout->binding_count) {
          if (set_layout->binding[b].stage[shader->stage].surface_index >= 0)
-            map->surface_count += set_layout->binding[b].array_size;
+            map->surface_count += set_layout->binding[b].hw_binding_size;
          if (set_layout->binding[b].stage[shader->stage].sampler_index >= 0)
-            map->sampler_count += set_layout->binding[b].array_size;
+            map->sampler_count += set_layout->binding[b].hw_binding_size;
          if (set_layout->binding[b].stage[shader->stage].image_index >= 0)
             map->image_count += set_layout->binding[b].array_size;
       }
@@ -317,31 +316,44 @@ anv_nir_apply_pipeline_layout(struct anv_pipeline *pipeline,
       BITSET_WORD b, _tmp;
       BITSET_FOREACH_SET(b, _tmp, state.set[set].used,
                          set_layout->binding_count) {
-         unsigned array_size = set_layout->binding[b].array_size;
+         struct anv_descriptor_set_binding_layout *binding =
+            &set_layout->binding[b];
 
-         if (set_layout->binding[b].stage[shader->stage].surface_index >= 0) {
+         if (binding->stage[shader->stage].surface_index >= 0) {
             state.set[set].surface_offsets[b] = surface;
-            for (unsigned i = 0; i < array_size; i++) {
-               map->surface_to_descriptor[surface + i].set = set;
-               map->surface_to_descriptor[surface + i].binding = b;
-               map->surface_to_descriptor[surface + i].index = i;
+            for (unsigned i = 0; i < binding->array_size; i++) {
+               struct anv_sampler *sampler = binding->immutable_samplers ?
+                  binding->immutable_samplers[i] : NULL;
+               uint8_t planes = sampler ? sampler->n_planes : 1;
+               for (uint8_t p = 0; p < planes; p++) {
+                  map->surface_to_descriptor[surface + i + p].set = set;
+                  map->surface_to_descriptor[surface + i + p].binding = b;
+                  map->surface_to_descriptor[surface + i + p].index = i;
+                  map->surface_to_descriptor[surface + i + p].plane = p;
+               }
             }
-            surface += array_size;
+            surface += binding->hw_binding_size;
          }
 
-         if (set_layout->binding[b].stage[shader->stage].sampler_index >= 0) {
+         if (binding->stage[shader->stage].sampler_index >= 0) {
             state.set[set].sampler_offsets[b] = sampler;
-            for (unsigned i = 0; i < array_size; i++) {
-               map->sampler_to_descriptor[sampler + i].set = set;
-               map->sampler_to_descriptor[sampler + i].binding = b;
-               map->sampler_to_descriptor[sampler + i].index = i;
+            for (unsigned i = 0; i < binding->array_size; i++) {
+               struct anv_sampler *anv_sampler = binding->immutable_samplers ?
+                  binding->immutable_samplers[i] : NULL;
+               uint8_t planes = anv_sampler ? anv_sampler->n_planes : 1;
+               for (uint8_t p = 0; p < planes; p++) {
+                  map->sampler_to_descriptor[sampler + i + p].set = set;
+                  map->sampler_to_descriptor[sampler + i + p].binding = b;
+                  map->sampler_to_descriptor[sampler + i + p].index = i;
+                  map->surface_to_descriptor[surface + i + p].plane = p;
+               }
             }
-            sampler += array_size;
+            sampler += binding->hw_binding_size;
          }
 
-         if (set_layout->binding[b].stage[shader->stage].image_index >= 0) {
+         if (binding->stage[shader->stage].image_index >= 0) {
             state.set[set].image_offsets[b] = image;
-            image += array_size;
+            image += binding->array_size;
          }
       }
    }
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 77ae7bb14dd..c2ce8ee43f7 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -1197,6 +1197,19 @@ struct anv_descriptor_set_binding_layout {
       int16_t image_index;
    } stage[MESA_SHADER_STAGES];
 
+   /* Index into the dynamic state array for a dynamic buffer */
+   int16_t hw_dynamic_offset_index;
+
+   /* Index into the flattend hardware binding table (might differ from
+    * descriptor_index because of mutliplanar surfaces)
+    */
+   uint16_t hw_binding_index;
+
+   /* Number of hardware binding to used in this binding (might differ from
+    * array_size because of multiplanar surfaces)
+    */
+   uint16_t hw_binding_size;
+
    /* Immutable samplers (or NULL if no immutable samplers) */
    struct anv_sampler **immutable_samplers;
 };
@@ -1208,6 +1221,11 @@ struct anv_descriptor_set_layout {
    /* Total size of the descriptor set with room for all array entries */
    uint16_t size;
 
+   /* Total size of the hardware binding table (might differ from size because
+    * of multiplanar surfaces)
+    */
+   uint16_t hw_size;
+
    /* Shader stages affected by this descriptor set */
    uint16_t shader_stages;
 
@@ -1385,6 +1403,9 @@ struct anv_pipeline_binding {
    /* Index in the binding */
    uint32_t index;
 
+   /* Plane in the binding index */
+   uint8_t plane;
+
    /* Input attachment index (relative to the subpass) */
    uint8_t input_attachment_index;
 
@@ -2541,6 +2562,7 @@ void anv_fill_buffer_surface_state(struct anv_device *device,
 
 struct anv_sampler {
    uint32_t state[4];
+   uint32_t n_planes;
 };
 
 struct anv_framebuffer {
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index 35593990198..367fddcf02a 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -1505,8 +1505,7 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
       uint32_t bo_offset = cmd_buffer->state.num_workgroups_offset;
 
       struct anv_state surface_state;
-      surface_state =
-         anv_cmd_buffer_alloc_surface_state(cmd_buffer);
+      surface_state = anv_cmd_buffer_alloc_surface_state(cmd_buffer);
 
       const enum isl_format format =
          anv_isl_format_for_descriptor_type(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
@@ -1532,7 +1531,6 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
    uint32_t image = 0;
    for (uint32_t s = 0; s < map->surface_count; s++) {
       struct anv_pipeline_binding *binding = &map->surface_to_descriptor[s];
-
       struct anv_state surface_state;
 
       if (binding->set == ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS) {
@@ -1722,7 +1720,8 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer,
    if (state->map == NULL)
       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
 
-   for (uint32_t s = 0; s < map->sampler_count; s++) {
+   uint32_t s = 0;
+   while (s < map->sampler_count) {
       struct anv_pipeline_binding *binding = &map->sampler_to_descriptor[s];
       struct anv_descriptor_set *set =
          cmd_buffer->state.descriptors[binding->set];
@@ -1730,19 +1729,25 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer,
       struct anv_descriptor *desc = &set->descriptors[offset + binding->index];
 
       if (desc->type != VK_DESCRIPTOR_TYPE_SAMPLER &&
-          desc->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+          desc->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
+         s += 1;
          continue;
+      }
 
       struct anv_sampler *sampler = desc->sampler;
 
       /* This can happen if we have an unfilled slot since TYPE_SAMPLER
        * happens to be zero.
        */
-      if (sampler == NULL)
+      if (sampler == NULL) {
+         s += 1;
          continue;
+      }
 
       memcpy(state->map + (s * 16),
              sampler->state, sizeof(sampler->state));
+
+      s += sampler->n_planes;
    }
 
    anv_state_flush(cmd_buffer->device, *state);
diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c
index d016aff4a54..81570825a54 100644
--- a/src/intel/vulkan/genX_state.c
+++ b/src/intel/vulkan/genX_state.c
@@ -171,6 +171,8 @@ VkResult genX(CreateSampler)(
    if (!sampler)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
+   sampler->n_planes = 1;
+
    uint32_t border_color_offset = device->border_colors.offset +
                                   pCreateInfo->borderColor * 64;
 
-- 
2.14.2



More information about the mesa-dev mailing list