<div dir="ltr"><div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br><br></div>Thanks for fixing this!<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 26, 2018 at 1:26 AM, Iago Toral Quiroga <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The spec states that descriptor set layouts can be destroyed almost<br>
at any time:<br>
<br>
   "VkDescriptorSetLayout objects may be accessed by commands that<br>
    operate on descriptor sets allocated using that layout, and those<br>
    descriptor sets must not be updated with vkUpdateDescriptorSets<br>
    after the descriptor set layout has been destroyed. Otherwise,<br>
    descriptor set layouts can be destroyed any time they are not in<br>
    use by an API command."<br>
<br>
v2: allocate off the device allocator with DEVICE scope. This is<br>
    expected to warnings in some CTS tests (Jason)<br>
<br>
Fixes the following work-in-progress CTS tests:<br>
dEQP-VK.api.descriptor_set.<wbr>descriptor_set_layout_<wbr>lifetime.graphics<br>
dEQP-VK.api.descriptor_set.<wbr>descriptor_set_layout_<wbr>lifetime.compute<br>
<br>
Suggested-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
---<br>
<br>
As expected, this patch adds the following warnings in CTS:<br>
<br>
Test case 'dEQP-VK.api.object_<wbr>management.alloc_callback_<wbr>fail.descriptor_set_layout_<wbr>empty'..<br>
  QualityWarning (Allocation callbacks not called)<br>
<br>
Test case 'dEQP-VK.api.object_<wbr>management.alloc_callback_<wbr>fail.descriptor_set_layout_<wbr>single'..<br>
  QualityWarning (Allocation callbacks not called)<br>
<br>
 src/intel/vulkan/anv_cmd_<wbr>buffer.c     |  6 ++----<br>
 src/intel/vulkan/anv_<wbr>descriptor_set.c | 23 ++++++++++++++++++-----<br>
 src/intel/vulkan/anv_private.h        | 23 +++++++++++++++++++++--<br>
 3 files changed, 41 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_cmd_<wbr>buffer.c b/src/intel/vulkan/anv_cmd_<wbr>buffer.c<br>
index bf80061c6d..521cf6b6a5 100644<br>
--- a/src/intel/vulkan/anv_cmd_<wbr>buffer.c<br>
+++ b/src/intel/vulkan/anv_cmd_<wbr>buffer.c<br>
@@ -913,8 +913,7 @@ void anv_CmdPushDescriptorSetKHR(<br>
<br>
    assert(_set < MAX_SETS);<br>
<br>
-   const struct anv_descriptor_set_layout *set_layout =<br>
-      layout->set[_set].layout;<br>
+   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;<br>
<br>
    struct anv_push_descriptor_set *push_set =<br>
       anv_cmd_buffer_get_push_<wbr>descriptor_set(cmd_buffer,<br>
@@ -1006,8 +1005,7 @@ void anv_<wbr>CmdPushDescriptorSetWithTempla<wbr>teKHR(<br>
<br>
    assert(_set < MAX_PUSH_DESCRIPTORS);<br>
<br>
-   const struct anv_descriptor_set_layout *set_layout =<br>
-      layout->set[_set].layout;<br>
+   struct anv_descriptor_set_layout *set_layout = layout->set[_set].layout;<br>
<br>
    struct anv_push_descriptor_set *push_set =<br>
       anv_cmd_buffer_get_push_<wbr>descriptor_set(cmd_buffer,<br>
diff --git a/src/intel/vulkan/anv_<wbr>descriptor_set.c b/src/intel/vulkan/anv_<wbr>descriptor_set.c<br>
index 1d4df264ae..edb829601e 100644<br>
--- a/src/intel/vulkan/anv_<wbr>descriptor_set.c<br>
+++ b/src/intel/vulkan/anv_<wbr>descriptor_set.c<br>
@@ -57,16 +57,21 @@ VkResult anv_CreateDescriptorSetLayout(<br>
    struct anv_descriptor_set_binding_<wbr>layout *bindings;<br>
    struct anv_sampler **samplers;<br>
<br>
+   /* We need to allocate decriptor set layouts off the device allocator<br>
+    * with DEVICE scope because they are reference counted and may not be<br>
+    * destroyed when vkDestroyDescriptorSetLayout is called.<br>
+    */<br>
    ANV_MULTIALLOC(ma);<br>
    anv_multialloc_add(&ma, &set_layout, 1);<br>
    anv_multialloc_add(&ma, &bindings, max_binding + 1);<br>
    anv_multialloc_add(&ma, &samplers, immutable_sampler_count);<br>
<br>
-   if (!anv_multialloc_alloc2(&ma, &device->alloc, pAllocator,<br>
-                              VK_SYSTEM_ALLOCATION_SCOPE_<wbr>OBJECT))<br>
+   if (!anv_multialloc_alloc(&ma, &device->alloc,<br>
+                             VK_SYSTEM_ALLOCATION_SCOPE_<wbr>DEVICE))<br>
       return vk_error(VK_ERROR_OUT_OF_HOST_<wbr>MEMORY);<br>
<br>
    memset(set_layout, 0, sizeof(*set_layout));<br>
+   set_layout->ref_cnt = 1;<br>
    set_layout->binding_count = max_binding + 1;<br>
<br>
    for (uint32_t b = 0; b <= max_binding; b++) {<br>
@@ -204,7 +209,7 @@ void anv_<wbr>DestroyDescriptorSetLayout(<br>
    if (!set_layout)<br>
       return;<br>
<br>
-   vk_free2(&device->alloc, pAllocator, set_layout);<br>
+   anv_descriptor_set_layout_<wbr>unref(device, set_layout);<br>
 }<br>
<br>
 static void<br>
@@ -246,6 +251,7 @@ VkResult anv_CreatePipelineLayout(<br>
       ANV_FROM_HANDLE(anv_<wbr>descriptor_set_layout, set_layout,<br>
                       pCreateInfo->pSetLayouts[set])<wbr>;<br>
       layout->set[set].layout = set_layout;<br>
+      anv_descriptor_set_layout_ref(<wbr>set_layout);<br>
<br>
       layout->set[set].dynamic_<wbr>offset_start = dynamic_offset_count;<br>
       for (uint32_t b = 0; b < set_layout->binding_count; b++) {<br>
@@ -290,6 +296,9 @@ void anv_DestroyPipelineLayout(<br>
    if (!pipeline_layout)<br>
       return;<br>
<br>
+   for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)<br>
+      anv_descriptor_set_layout_<wbr>unref(device, pipeline_layout->set[i].<wbr>layout);<br>
+<br>
    vk_free2(&device->alloc, pAllocator, pipeline_layout);<br>
 }<br>
<br>
@@ -423,7 +432,7 @@ struct surface_state_free_list_entry {<br>
 VkResult<br>
 anv_descriptor_set_create(<wbr>struct anv_device *device,<br>
                           struct anv_descriptor_pool *pool,<br>
-                          const struct anv_descriptor_set_layout *layout,<br>
+                          struct anv_descriptor_set_layout *layout,<br>
                           struct anv_descriptor_set **out_set)<br>
 {<br>
    struct anv_descriptor_set *set;<br>
@@ -455,8 +464,10 @@ anv_descriptor_set_create(<wbr>struct anv_device *device,<br>
       }<br>
    }<br>
<br>
-   set->size = size;<br>
    set->layout = layout;<br>
+   anv_descriptor_set_layout_ref(<wbr>layout);<br>
+<br>
+   set->size = size;<br>
    set->buffer_views =<br>
       (struct anv_buffer_view *) &set->descriptors[layout-><wbr>size];<br>
    set->buffer_count = layout->buffer_count;<br>
@@ -512,6 +523,8 @@ anv_descriptor_set_destroy(<wbr>struct anv_device *device,<br>
                            struct anv_descriptor_pool *pool,<br>
                            struct anv_descriptor_set *set)<br>
 {<br>
+   anv_descriptor_set_layout_<wbr>unref(device, set->layout);<br>
+<br>
    /* Put the buffer view surface state back on the free list. */<br>
    for (uint32_t b = 0; b < set->buffer_count; b++) {<br>
       struct surface_state_free_list_entry *entry =<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index b351c6f63b..701a49823e 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -1199,6 +1199,9 @@ struct anv_descriptor_set_binding_<wbr>layout {<br>
 };<br>
<br>
 struct anv_descriptor_set_layout {<br>
+   /* Descriptor set layouts can be destroyed at almost any time */<br>
+   uint32_t ref_cnt;<br>
+<br>
    /* Number of bindings in this descriptor set */<br>
    uint16_t binding_count;<br>
<br>
@@ -1218,6 +1221,22 @@ struct anv_descriptor_set_layout {<br>
    struct anv_descriptor_set_binding_<wbr>layout binding[0];<br>
 };<br>
<br>
+static inline void<br>
+anv_descriptor_set_layout_<wbr>ref(struct anv_descriptor_set_layout *layout)<br>
+{<br>
+   assert(layout && layout->ref_cnt >= 1);<br>
+   p_atomic_inc(&layout->ref_cnt)<wbr>;<br>
+}<br>
+<br>
+static inline void<br>
+anv_descriptor_set_layout_<wbr>unref(struct anv_device *device,<br>
+                                struct anv_descriptor_set_layout *layout)<br>
+{<br>
+   assert(layout && layout->ref_cnt >= 1);<br>
+   if (p_atomic_dec_zero(&layout-><wbr>ref_cnt))<br>
+      vk_free(&device->alloc, layout);<br>
+}<br>
+<br>
 struct anv_descriptor {<br>
    VkDescriptorType type;<br>
<br>
@@ -1239,7 +1258,7 @@ struct anv_descriptor {<br>
 };<br>
<br>
 struct anv_descriptor_set {<br>
-   const struct anv_descriptor_set_layout *layout;<br>
+   struct anv_descriptor_set_layout *layout;<br>
    uint32_t size;<br>
    uint32_t buffer_count;<br>
    struct anv_buffer_view *buffer_views;<br>
@@ -1363,7 +1382,7 @@ anv_descriptor_set_write_<wbr>template(struct anv_descriptor_set *set,<br>
 VkResult<br>
 anv_descriptor_set_create(<wbr>struct anv_device *device,<br>
                           struct anv_descriptor_pool *pool,<br>
-                          const struct anv_descriptor_set_layout *layout,<br>
+                          struct anv_descriptor_set_layout *layout,<br>
                           struct anv_descriptor_set **out_set);<br>
<br>
 void<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.14.1<br>
<br>
</font></span></blockquote></div><br></div>