anv: Completely rework descriptor set layouts
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 14 Oct 2015 22:18:49 +0000 (15:18 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Thu, 15 Oct 2015 01:38:33 +0000 (18:38 -0700)
This patch reworks a bunch of stuff in the way we do descriptor set
layouts.  Our previous approach had a couple of problems.  First, it was
based on a misunderstanding of arrays in descriptor sets.  Second, it
didn't properly handle descriptor sets where some bindings were missing
stages.  The new apporach should be correct and also makes some operations,
particularly those on the hot-path, a bit easier.

We use the descriptor set layout for four things:

 1) To determine the map from bindings to the actual flattened descriptor
    set in vkUpdateDescriptorSets().

 2) To determine the descriptor <-> binding table entry mapping to use in
    anv_cmd_buffer_flush_descriptor_sets().

 3) To determine the mappings of dynamic indices.

 4) To determine the (set, binding, array index) -> binding table entry
    mapping inside of shaders.

The new approach is directly taylored towards these operations.

src/vulkan/anv_cmd_buffer.c
src/vulkan/anv_compiler.cpp
src/vulkan/anv_device.c
src/vulkan/anv_nir_apply_dynamic_offsets.c
src/vulkan/anv_pipeline.c
src/vulkan/anv_private.h

index 28d9dd9d69426e64dbf45643d27857b4505b1e8e..718499d60c8133f19398c6d9da1a500267558aec 100644 (file)
@@ -483,7 +483,7 @@ void anv_CmdBindDescriptorSets(
          cmd_buffer->state.descriptors_dirty |= set_layout->shader_stages;
       }
 
-      if (set_layout->num_dynamic_buffers > 0) {
+      if (set_layout->dynamic_offset_count > 0) {
          VkShaderStage s;
          for_each_bit(s, set_layout->shader_stages) {
             anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, s,
@@ -492,13 +492,13 @@ void anv_CmdBindDescriptorSets(
                cmd_buffer->state.push_constants[s]->dynamic_offsets +
                layout->set[firstSet + i].dynamic_offset_start;
 
-            memcpy(offsets, pDynamicOffsets + dynamic_slot,
-                   set_layout->num_dynamic_buffers * sizeof(*pDynamicOffsets));
+            typed_memcpy(offsets, pDynamicOffsets + dynamic_slot,
+                         set_layout->dynamic_offset_count);
 
          }
          cmd_buffer->state.push_constants_dirty |= set_layout->shader_stages;
 
-         dynamic_slot += set_layout->num_dynamic_buffers;
+         dynamic_slot += set_layout->dynamic_offset_count;
       }
    }
 }
@@ -594,41 +594,35 @@ anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
    if (layout == NULL)
       return VK_SUCCESS;
 
-   for (uint32_t set = 0; set < layout->num_sets; set++) {
-      struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
-      struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
-      struct anv_descriptor_slot *surface_slots =
-         set_layout->stage[stage].surface_start;
-
-      uint32_t start = bias + layout->set[set].stage[stage].surface_start;
-
-      for (uint32_t b = 0; b < set_layout->stage[stage].surface_count; b++) {
-         struct anv_descriptor *desc =
-            &d->set->descriptors[surface_slots[b].index];
-
-         const struct anv_state *surface_state;
-         struct anv_bo *bo;
-         uint32_t bo_offset;
-
-         switch (desc->type) {
-         case ANV_DESCRIPTOR_TYPE_EMPTY:
-         case ANV_DESCRIPTOR_TYPE_SAMPLER:
-            continue;
-         case ANV_DESCRIPTOR_TYPE_BUFFER_VIEW:
-            surface_state = &desc->buffer_view->surface_state;
-            bo = desc->buffer_view->bo;
-            bo_offset = desc->buffer_view->offset;
-            break;
-         case ANV_DESCRIPTOR_TYPE_IMAGE_VIEW:
-            surface_state = &desc->image_view->nonrt_surface_state;
-            bo = desc->image_view->bo;
-            bo_offset = desc->image_view->offset;
-            break;
-         }
-
-         bt_map[start + b] = surface_state->offset + state_offset;
-         add_surface_state_reloc(cmd_buffer, *surface_state, bo, bo_offset);
+   for (uint32_t s = 0; s < layout->stage[stage].surface_count; s++) {
+      struct anv_pipeline_binding *binding =
+         &layout->stage[stage].surface_to_descriptor[s];
+      struct anv_descriptor_set *set =
+         cmd_buffer->state.descriptors[binding->set].set;
+      struct anv_descriptor *desc = &set->descriptors[binding->offset];
+
+      const struct anv_state *surface_state;
+      struct anv_bo *bo;
+      uint32_t bo_offset;
+
+      switch (desc->type) {
+      case ANV_DESCRIPTOR_TYPE_EMPTY:
+      case ANV_DESCRIPTOR_TYPE_SAMPLER:
+         continue;
+      case ANV_DESCRIPTOR_TYPE_BUFFER_VIEW:
+         surface_state = &desc->buffer_view->surface_state;
+         bo = desc->buffer_view->bo;
+         bo_offset = desc->buffer_view->offset;
+         break;
+      case ANV_DESCRIPTOR_TYPE_IMAGE_VIEW:
+         surface_state = &desc->image_view->nonrt_surface_state;
+         bo = desc->image_view->bo;
+         bo_offset = desc->image_view->offset;
+         break;
       }
+
+      bt_map[bias + s] = surface_state->offset + state_offset;
+      add_surface_state_reloc(cmd_buffer, *surface_state, bo, bo_offset);
    }
 
    return VK_SUCCESS;
@@ -656,26 +650,20 @@ anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
    if (state->map == NULL)
       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
 
-   for (uint32_t set = 0; set < layout->num_sets; set++) {
-      struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
-      struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
-      struct anv_descriptor_slot *sampler_slots =
-         set_layout->stage[stage].sampler_start;
-
-      uint32_t start = layout->set[set].stage[stage].sampler_start;
+   for (uint32_t s = 0; s < layout->stage[stage].sampler_count; s++) {
+      struct anv_pipeline_binding *binding =
+         &layout->stage[stage].sampler_to_descriptor[s];
+      struct anv_descriptor_set *set =
+         cmd_buffer->state.descriptors[binding->set].set;
+      struct anv_descriptor *desc = &set->descriptors[binding->offset];
 
-      for (uint32_t b = 0; b < set_layout->stage[stage].sampler_count; b++) {
-         struct anv_descriptor *desc =
-            &d->set->descriptors[sampler_slots[b].index];
+      if (desc->type != ANV_DESCRIPTOR_TYPE_SAMPLER)
+         continue;
 
-         if (desc->type != ANV_DESCRIPTOR_TYPE_SAMPLER)
-            continue;
+      struct anv_sampler *sampler = desc->sampler;
 
-         struct anv_sampler *sampler = desc->sampler;
-
-         memcpy(state->map + (start + b) * 16,
-                sampler->state, sizeof(sampler->state));
-      }
+      memcpy(state->map + (s * 16),
+             sampler->state, sizeof(sampler->state));
    }
 
    return VK_SUCCESS;
index 759ec7ae4d9d2bc618a29382dbe997701b95d82a..bf931fe886f53be895bba449c45dc16a1cd91401 100644 (file)
@@ -92,13 +92,20 @@ set_binding_table_layout(struct brw_stage_prog_data *prog_data,
 
    k = bias;
    map = prog_data->map_entries;
-   for (uint32_t i = 0; i < layout->num_sets; i++) {
-      prog_data->bind_map[i].index = map;
-      for (uint32_t j = 0; j < layout->set[i].layout->stage[stage].surface_count; j++)
-         *map++ = k++;
+   for (uint32_t set = 0; set < layout->num_sets; set++) {
+      prog_data->bind_map[set].index = map;
+      unsigned index_count = 0;
+      for (uint32_t b = 0; b < layout->set[set].layout->binding_count; b++) {
+         if (layout->set[set].layout->binding[b].stage[stage].surface_index < 0)
+            continue;
+
+         unsigned array_size = layout->set[set].layout->binding[b].array_size;
+         for (uint32_t i = 0; i < array_size; i++)
+            *map++ = k++;
+         index_count += array_size;
+      }
 
-      prog_data->bind_map[i].index_count =
-         layout->set[i].layout->stage[stage].surface_count;
+      prog_data->bind_map[set].index_count = index_count;
    }
 
    return VK_SUCCESS;
index 9625cc61252359bfd8c85199115f17d3bb8763c3..98c1b2334e6b0956f2ccf60e298c6fa4ae2acb18 100644 (file)
@@ -1440,28 +1440,48 @@ VkResult anv_CreateDescriptorSetLayout(
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
    struct anv_descriptor_set_layout *set_layout;
+   uint32_t s;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
 
+   size_t size = sizeof(struct anv_descriptor_set_layout) +
+                 pCreateInfo->count * sizeof(set_layout->binding[0]);
+
+   set_layout = anv_device_alloc(device, size, 8,
+                                 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+   if (!set_layout)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   set_layout->binding_count = pCreateInfo->count;
+   set_layout->shader_stages = 0;
+   set_layout->size = 0;
+
+   /* Initialize all binding_layout entries to -1 */
+   memset(set_layout->binding, -1,
+          pCreateInfo->count * sizeof(set_layout->binding[0]));
+
    uint32_t sampler_count[VK_SHADER_STAGE_NUM] = { 0, };
    uint32_t surface_count[VK_SHADER_STAGE_NUM] = { 0, };
-   uint32_t num_dynamic_buffers = 0;
-   uint32_t count = 0;
-   VkShaderStageFlags stages = 0;
-   uint32_t s;
+   uint32_t dynamic_offset_count = 0;
+
+   for (uint32_t b = 0; b < pCreateInfo->count; b++) {
+      uint32_t array_size = MAX2(1, pCreateInfo->pBinding[b].arraySize);
+      set_layout->binding[b].array_size = array_size;
+      set_layout->size += array_size;
 
-   for (uint32_t i = 0; i < pCreateInfo->count; i++) {
-      switch (pCreateInfo->pBinding[i].descriptorType) {
+      switch (pCreateInfo->pBinding[b].descriptorType) {
       case VK_DESCRIPTOR_TYPE_SAMPLER:
       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
-         for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
-            sampler_count[s] += pCreateInfo->pBinding[i].arraySize;
+         for_each_bit(s, pCreateInfo->pBinding[b].stageFlags) {
+            set_layout->binding[b].stage[s].sampler_index = sampler_count[s];
+            sampler_count[s] += array_size;
+         }
          break;
       default:
          break;
       }
 
-      switch (pCreateInfo->pBinding[i].descriptorType) {
+      switch (pCreateInfo->pBinding[b].descriptorType) {
       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
@@ -1472,114 +1492,29 @@ VkResult anv_CreateDescriptorSetLayout(
       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
-         for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
-            surface_count[s] += pCreateInfo->pBinding[i].arraySize;
+         for_each_bit(s, pCreateInfo->pBinding[b].stageFlags) {
+            set_layout->binding[b].stage[s].surface_index = surface_count[s];
+            surface_count[s] += array_size;
+         }
          break;
       default:
          break;
       }
 
-      switch (pCreateInfo->pBinding[i].descriptorType) {
+      switch (pCreateInfo->pBinding[b].descriptorType) {
       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
-         num_dynamic_buffers += pCreateInfo->pBinding[i].arraySize;
+         set_layout->binding[b].dynamic_offset_index = dynamic_offset_count;
+         dynamic_offset_count += array_size;
          break;
       default:
          break;
       }
 
-      stages |= pCreateInfo->pBinding[i].stageFlags;
-      count += pCreateInfo->pBinding[i].arraySize;
+      set_layout->shader_stages |= pCreateInfo->pBinding[b].stageFlags;
    }
 
-   uint32_t sampler_total = 0;
-   uint32_t surface_total = 0;
-   for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-      sampler_total += sampler_count[s];
-      surface_total += surface_count[s];
-   }
-
-   size_t size = sizeof(*set_layout) +
-      (sampler_total + surface_total) * sizeof(set_layout->entries[0]);
-   set_layout = anv_device_alloc(device, size, 8,
-                                 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-   if (!set_layout)
-      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   set_layout->num_dynamic_buffers = num_dynamic_buffers;
-   set_layout->count = count;
-   set_layout->shader_stages = stages;
-
-   struct anv_descriptor_slot *p = set_layout->entries;
-   struct anv_descriptor_slot *sampler[VK_SHADER_STAGE_NUM];
-   struct anv_descriptor_slot *surface[VK_SHADER_STAGE_NUM];
-   for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-      set_layout->stage[s].surface_count = surface_count[s];
-      set_layout->stage[s].surface_start = surface[s] = p;
-      p += surface_count[s];
-      set_layout->stage[s].sampler_count = sampler_count[s];
-      set_layout->stage[s].sampler_start = sampler[s] = p;
-      p += sampler_count[s];
-   }
-
-   uint32_t descriptor = 0;
-   int8_t dynamic_slot = 0;
-   bool is_dynamic;
-   for (uint32_t i = 0; i < pCreateInfo->count; i++) {
-      switch (pCreateInfo->pBinding[i].descriptorType) {
-      case VK_DESCRIPTOR_TYPE_SAMPLER:
-      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
-         for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
-            for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
-               sampler[s]->index = descriptor + j;
-               sampler[s]->dynamic_slot = -1;
-               sampler[s]++;
-            }
-         break;
-      default:
-         break;
-      }
-
-      switch (pCreateInfo->pBinding[i].descriptorType) {
-      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
-      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
-         is_dynamic = true;
-         break;
-      default:
-         is_dynamic = false;
-         break;
-      }
-
-      switch (pCreateInfo->pBinding[i].descriptorType) {
-      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
-      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
-      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
-      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
-      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
-      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
-      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
-      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
-      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
-      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
-         for_each_bit(s, pCreateInfo->pBinding[i].stageFlags)
-            for (uint32_t j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
-               surface[s]->index = descriptor + j;
-               if (is_dynamic)
-                  surface[s]->dynamic_slot = dynamic_slot + j;
-               else
-                  surface[s]->dynamic_slot = -1;
-               surface[s]++;
-            }
-         break;
-      default:
-         break;
-      }
-
-      if (is_dynamic)
-         dynamic_slot += pCreateInfo->pBinding[i].arraySize;
-
-      descriptor += pCreateInfo->pBinding[i].arraySize;
-   }
+   set_layout->dynamic_offset_count = dynamic_offset_count;
 
    *pSetLayout = anv_descriptor_set_layout_to_handle(set_layout);
 
@@ -1627,7 +1562,7 @@ anv_descriptor_set_create(struct anv_device *device,
                           struct anv_descriptor_set **out_set)
 {
    struct anv_descriptor_set *set;
-   size_t size = sizeof(*set) + layout->count * sizeof(set->descriptors[0]);
+   size_t size = sizeof(*set) + layout->size * sizeof(set->descriptors[0]);
 
    set = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
    if (!set)
index 1f6c64a9e02507ef115c177f56f7af8d4167be19..9d29c3c23eaee69675d2f4318103cfeab649faff 100644 (file)
@@ -39,7 +39,6 @@ apply_dynamic_offsets_block(nir_block *block, void *void_state)
 {
    struct apply_dynamic_offsets_state *state = void_state;
    struct anv_descriptor_set_layout *set_layout;
-   const struct anv_descriptor_slot *slot;
 
    nir_foreach_instr_safe(block, instr) {
       if (instr->type != nir_instr_type_intrinsic)
@@ -69,19 +68,18 @@ apply_dynamic_offsets_block(nir_block *block, void *void_state)
       }
 
       set_layout = state->layout->set[set].layout;
-      slot = &set_layout->stage[state->stage].surface_start[binding];
-      if (slot->dynamic_slot < 0)
+      if (set_layout->binding[binding].dynamic_offset_index < 0)
          continue;
 
-      uint32_t dynamic_index = state->layout->set[set].dynamic_offset_start +
-                               slot->dynamic_slot;
+      uint32_t index = state->layout->set[set].dynamic_offset_start +
+                       set_layout->binding[binding].dynamic_offset_index;
 
       state->builder.cursor = nir_before_instr(&intrin->instr);
 
       nir_intrinsic_instr *offset_load =
          nir_intrinsic_instr_create(state->shader, nir_intrinsic_load_uniform);
       offset_load->num_components = 1;
-      offset_load->const_index[0] = state->indices_start + dynamic_index;
+      offset_load->const_index[0] = state->indices_start + index;
       offset_load->const_index[1] = 0;
       nir_ssa_dest_init(&offset_load->instr, &offset_load->dest, 1, NULL);
       nir_builder_instr_insert(&state->builder, &offset_load->instr);
index 75f640154cc50307c175076b46374592df21ed88..84e023c781a30ba8998e93c7dc953b2541d803a5 100644 (file)
@@ -458,48 +458,101 @@ VkResult anv_CreatePipelineLayout(
     VkPipelineLayout*                           pPipelineLayout)
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
-   struct anv_pipeline_layout *layout;
+   struct anv_pipeline_layout l, *layout;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
 
-   layout = anv_device_alloc(device, sizeof(*layout), 8,
-                             VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
-   if (layout == NULL)
-      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   l.num_sets = pCreateInfo->descriptorSetCount;
+
+   unsigned dynamic_offset_count = 0;
+
+   memset(l.stage, 0, sizeof(l.stage));
+   for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
+      ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
+                      pCreateInfo->pSetLayouts[set]);
+      l.set[set].layout = set_layout;
+
+      l.set[set].dynamic_offset_start = dynamic_offset_count;
+      for (uint32_t b = 0; b < set_layout->binding_count; b++) {
+         if (set_layout->binding[b].dynamic_offset_index >= 0)
+            dynamic_offset_count += set_layout->binding[b].array_size;
+      }
+
+      for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+         l.set[set].stage[s].surface_start = l.stage[s].surface_count;
+         l.set[set].stage[s].sampler_start = l.stage[s].sampler_count;
+
+         for (uint32_t b = 0; b < set_layout->binding_count; b++) {
+            unsigned array_size = set_layout->binding[b].array_size;
 
-   layout->num_sets = pCreateInfo->descriptorSetCount;
+            if (set_layout->binding[b].stage[s].surface_index >= 0) {
+               l.stage[s].surface_count += array_size;
 
-   uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
-   uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
+               if (set_layout->binding[b].dynamic_offset_index >= 0)
+                  l.stage[s].has_dynamic_offsets = true;
+            }
 
-   for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-      layout->stage[s].has_dynamic_offsets = false;
-      layout->stage[s].surface_count = 0;
-      layout->stage[s].sampler_count = 0;
+            if (set_layout->binding[b].stage[s].sampler_index >= 0)
+               l.stage[s].sampler_count += array_size;
+         }
+      }
    }
 
-   uint32_t num_dynamic_offsets = 0;
-   for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
-      ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
-                      pCreateInfo->pSetLayouts[i]);
-
-      layout->set[i].layout = set_layout;
-      layout->set[i].dynamic_offset_start = num_dynamic_offsets;
-      num_dynamic_offsets += set_layout->num_dynamic_buffers;
-      for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
-         if (set_layout->num_dynamic_buffers > 0)
-            layout->stage[s].has_dynamic_offsets = true;
-
-         layout->set[i].stage[s].surface_start = surface_start[s];
-         surface_start[s] += set_layout->stage[s].surface_count;
-         layout->set[i].stage[s].sampler_start = sampler_start[s];
-         sampler_start[s] += set_layout->stage[s].sampler_count;
-
-         layout->stage[s].surface_count += set_layout->stage[s].surface_count;
-         layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
+   unsigned num_bindings = 0;
+   for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++)
+      num_bindings += l.stage[s].surface_count + l.stage[s].sampler_count;
+
+   size_t size = sizeof(*layout) + num_bindings * sizeof(layout->entries[0]);
+
+   layout = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+   if (layout == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   /* Now we can actually build our surface and sampler maps */
+   struct anv_pipeline_binding *entry = layout->entries;
+   for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
+      l.stage[s].surface_to_descriptor = entry;
+      entry += l.stage[s].surface_count;
+      l.stage[s].sampler_to_descriptor = entry;
+      entry += l.stage[s].sampler_count;
+
+      int surface = 0;
+      int sampler = 0;
+      for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
+         struct anv_descriptor_set_layout *set_layout = l.set[set].layout;
+
+         unsigned set_offset = 0;
+         for (uint32_t b = 0; b < set_layout->binding_count; b++) {
+            unsigned array_size = set_layout->binding[b].array_size;
+
+            if (set_layout->binding[b].stage[s].surface_index >= 0) {
+               assert(surface == l.set[set].stage[s].surface_start +
+                                 set_layout->binding[b].stage[s].surface_index);
+               for (unsigned i = 0; i < array_size; i++) {
+                  l.stage[s].surface_to_descriptor[surface + i].set = set;
+                  l.stage[s].surface_to_descriptor[surface + i].offset = set_offset + i;
+               }
+               surface += array_size;
+            }
+
+            if (set_layout->binding[b].stage[s].sampler_index >= 0) {
+               assert(sampler == l.set[set].stage[s].sampler_start +
+                                 set_layout->binding[b].stage[s].sampler_index);
+               for (unsigned i = 0; i < array_size; i++) {
+                  l.stage[s].sampler_to_descriptor[sampler + i].set = set;
+                  l.stage[s].sampler_to_descriptor[sampler + i].offset = set_offset + i;
+               }
+               sampler += array_size;
+            }
+
+            set_offset += array_size;
+         }
       }
    }
 
+   /* Finally, we're done setting it up, copy into the allocated version */
+   *layout = l;
+
    *pPipelineLayout = anv_pipeline_layout_to_handle(layout);
 
    return VK_SUCCESS;
index 6bc781fa072ca5811b5cd2154592072894724685..523e6dfa74749b72ce7ed164efe554603da181fd 100644 (file)
@@ -660,23 +660,37 @@ struct anv_device_memory {
    void *                                       map;
 };
 
-struct anv_descriptor_slot {
-   int8_t dynamic_slot;
-   uint8_t index;
-};
+struct anv_descriptor_set_binding_layout {
+   /* Number of array elements in this binding */
+   uint16_t array_size;
+
+   /* Index into the dynamic state array for a dynamic buffer */
+   int16_t dynamic_offset_index;
 
-struct anv_descriptor_set_layout {
    struct {
-      uint32_t surface_count;
-      struct anv_descriptor_slot *surface_start;
-      uint32_t sampler_count;
-      struct anv_descriptor_slot *sampler_start;
+      /* Index into the binding table for the associated surface */
+      int16_t surface_index;
+
+      /* Index into the sampler table for the associated sampler */
+      int16_t sampler_index;
    } stage[VK_SHADER_STAGE_NUM];
+};
+
+struct anv_descriptor_set_layout {
+   /* Number of bindings in this descriptor set */
+   uint16_t binding_count;
+
+   /* Total size of the descriptor set with room for all array entries */
+   uint16_t size;
+
+   /* Shader stages affected by this descriptor set */
+   uint16_t shader_stages;
+
+   /* Number of dynamic offsets used by this descriptor set */
+   uint16_t dynamic_offset_count;
 
-   uint32_t count;
-   uint32_t num_dynamic_buffers;
-   VkShaderStageFlags shader_stages;
-   struct anv_descriptor_slot entries[0];
+   /* Don't use this directly */
+   struct anv_descriptor_set_binding_layout binding[0];
 };
 
 enum anv_descriptor_type {
@@ -718,6 +732,14 @@ anv_descriptor_set_destroy(struct anv_device *device,
 #define MAX_DYNAMIC_BUFFERS 16
 #define MAX_IMAGES 8
 
+struct anv_pipeline_binding {
+   /* The descriptor set this surface corresponds to */
+   uint16_t set;
+
+   /* Offset into the descriptor set */
+   uint16_t offset;
+};
+
 struct anv_pipeline_layout {
    struct {
       struct anv_descriptor_set_layout *layout;
@@ -733,8 +755,12 @@ struct anv_pipeline_layout {
    struct {
       bool has_dynamic_offsets;
       uint32_t surface_count;
+      struct anv_pipeline_binding *surface_to_descriptor;
       uint32_t sampler_count;
+      struct anv_pipeline_binding *sampler_to_descriptor;
    } stage[VK_SHADER_STAGE_NUM];
+
+   struct anv_pipeline_binding entries[0];
 };
 
 struct anv_buffer {