anv/descriptor_set: add reference counting for descriptor set layouts
authorIago Toral Quiroga <itoral@igalia.com>
Thu, 25 Jan 2018 08:43:22 +0000 (09:43 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Fri, 26 Jan 2018 13:06:46 +0000 (14:06 +0100)
The spec states that descriptor set layouts can be destroyed almost
at any time:

   "VkDescriptorSetLayout objects may be accessed by commands that
    operate on descriptor sets allocated using that layout, and those
    descriptor sets must not be updated with vkUpdateDescriptorSets
    after the descriptor set layout has been destroyed. Otherwise,
    descriptor set layouts can be destroyed any time they are not in
    use by an API command."

v2: allocate off the device allocator with DEVICE scope (Jason)

Fixes the following work-in-progress CTS tests:
dEQP-VK.api.descriptor_set.descriptor_set_layout_lifetime.graphics
dEQP-VK.api.descriptor_set.descriptor_set_layout_lifetime.compute

Suggested-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/intel/vulkan/anv_cmd_buffer.c
src/intel/vulkan/anv_descriptor_set.c
src/intel/vulkan/anv_private.h

index bf80061c6d45d6eab8c2d85ff7c9498519db607d..521cf6b6a544ff8633c8cf915129747322d9d3c9 100644 (file)
@@ -913,8 +913,7 @@ void anv_CmdPushDescriptorSetKHR(
 
    assert(_set < MAX_SETS);
 
-   const struct anv_descriptor_set_layout *set_layout =
-      layout->set[_set].layout;
+   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
 
    struct anv_push_descriptor_set *push_set =
       anv_cmd_buffer_get_push_descriptor_set(cmd_buffer,
@@ -1006,8 +1005,7 @@ void anv_CmdPushDescriptorSetWithTemplateKHR(
 
    assert(_set < MAX_PUSH_DESCRIPTORS);
 
-   const struct anv_descriptor_set_layout *set_layout =
-      layout->set[_set].layout;
+   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;
 
    struct anv_push_descriptor_set *push_set =
       anv_cmd_buffer_get_push_descriptor_set(cmd_buffer,
index 1d4df264ae6e93717532a3f0a7e04461cc070252..edb829601e8bca8f3ba0bb1e4f62319ab5035d1c 100644 (file)
@@ -57,16 +57,21 @@ VkResult anv_CreateDescriptorSetLayout(
    struct anv_descriptor_set_binding_layout *bindings;
    struct anv_sampler **samplers;
 
+   /* We need to allocate decriptor set layouts off the device allocator
+    * with DEVICE scope because they are reference counted and may not be
+    * destroyed when vkDestroyDescriptorSetLayout is called.
+    */
    ANV_MULTIALLOC(ma);
    anv_multialloc_add(&ma, &set_layout, 1);
    anv_multialloc_add(&ma, &bindings, max_binding + 1);
    anv_multialloc_add(&ma, &samplers, immutable_sampler_count);
 
-   if (!anv_multialloc_alloc2(&ma, &device->alloc, pAllocator,
-                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
+   if (!anv_multialloc_alloc(&ma, &device->alloc,
+                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
    memset(set_layout, 0, sizeof(*set_layout));
+   set_layout->ref_cnt = 1;
    set_layout->binding_count = max_binding + 1;
 
    for (uint32_t b = 0; b <= max_binding; b++) {
@@ -204,7 +209,7 @@ void anv_DestroyDescriptorSetLayout(
    if (!set_layout)
       return;
 
-   vk_free2(&device->alloc, pAllocator, set_layout);
+   anv_descriptor_set_layout_unref(device, set_layout);
 }
 
 static void
@@ -246,6 +251,7 @@ VkResult anv_CreatePipelineLayout(
       ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
                       pCreateInfo->pSetLayouts[set]);
       layout->set[set].layout = set_layout;
+      anv_descriptor_set_layout_ref(set_layout);
 
       layout->set[set].dynamic_offset_start = dynamic_offset_count;
       for (uint32_t b = 0; b < set_layout->binding_count; b++) {
@@ -290,6 +296,9 @@ void anv_DestroyPipelineLayout(
    if (!pipeline_layout)
       return;
 
+   for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
+      anv_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
+
    vk_free2(&device->alloc, pAllocator, pipeline_layout);
 }
 
@@ -423,7 +432,7 @@ struct surface_state_free_list_entry {
 VkResult
 anv_descriptor_set_create(struct anv_device *device,
                           struct anv_descriptor_pool *pool,
-                          const struct anv_descriptor_set_layout *layout,
+                          struct anv_descriptor_set_layout *layout,
                           struct anv_descriptor_set **out_set)
 {
    struct anv_descriptor_set *set;
@@ -455,8 +464,10 @@ anv_descriptor_set_create(struct anv_device *device,
       }
    }
 
-   set->size = size;
    set->layout = layout;
+   anv_descriptor_set_layout_ref(layout);
+
+   set->size = size;
    set->buffer_views =
       (struct anv_buffer_view *) &set->descriptors[layout->size];
    set->buffer_count = layout->buffer_count;
@@ -512,6 +523,8 @@ anv_descriptor_set_destroy(struct anv_device *device,
                            struct anv_descriptor_pool *pool,
                            struct anv_descriptor_set *set)
 {
+   anv_descriptor_set_layout_unref(device, set->layout);
+
    /* Put the buffer view surface state back on the free list. */
    for (uint32_t b = 0; b < set->buffer_count; b++) {
       struct surface_state_free_list_entry *entry =
index b351c6f63b33a7ba7a19efca3ff3680030f660e0..701a49823e4bbbc7bb6fb2bc2f7f8c403dcdfa13 100644 (file)
@@ -1199,6 +1199,9 @@ struct anv_descriptor_set_binding_layout {
 };
 
 struct anv_descriptor_set_layout {
+   /* Descriptor set layouts can be destroyed at almost any time */
+   uint32_t ref_cnt;
+
    /* Number of bindings in this descriptor set */
    uint16_t binding_count;
 
@@ -1218,6 +1221,22 @@ struct anv_descriptor_set_layout {
    struct anv_descriptor_set_binding_layout binding[0];
 };
 
+static inline void
+anv_descriptor_set_layout_ref(struct anv_descriptor_set_layout *layout)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   p_atomic_inc(&layout->ref_cnt);
+}
+
+static inline void
+anv_descriptor_set_layout_unref(struct anv_device *device,
+                                struct anv_descriptor_set_layout *layout)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   if (p_atomic_dec_zero(&layout->ref_cnt))
+      vk_free(&device->alloc, layout);
+}
+
 struct anv_descriptor {
    VkDescriptorType type;
 
@@ -1239,7 +1258,7 @@ struct anv_descriptor {
 };
 
 struct anv_descriptor_set {
-   const struct anv_descriptor_set_layout *layout;
+   struct anv_descriptor_set_layout *layout;
    uint32_t size;
    uint32_t buffer_count;
    struct anv_buffer_view *buffer_views;
@@ -1363,7 +1382,7 @@ anv_descriptor_set_write_template(struct anv_descriptor_set *set,
 VkResult
 anv_descriptor_set_create(struct anv_device *device,
                           struct anv_descriptor_pool *pool,
-                          const struct anv_descriptor_set_layout *layout,
+                          struct anv_descriptor_set_layout *layout,
                           struct anv_descriptor_set **out_set);
 
 void