<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jan 25, 2018 at 4:24 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>
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>
 src/intel/vulkan/anv_cmd_<wbr>buffer.c     |  6 ++----<br>
 src/intel/vulkan/anv_<wbr>descriptor_set.c | 17 ++++++++++++++---<br>
 src/intel/vulkan/anv_private.h        | 26 ++++++++++++++++++++++++--<br>
 3 files changed, 40 insertions(+), 9 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 bf80061c6d4..521cf6b6a54 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 1d4df264ae6..99122aed229 100644<br>
--- a/src/intel/vulkan/anv_<wbr>descriptor_set.c<br>
+++ b/src/intel/vulkan/anv_<wbr>descriptor_set.c<br>
@@ -67,6 +67,8 @@ VkResult anv_CreateDescriptorSetLayout(<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->allocator = pAllocator;<br></blockquote><div><br></div><div>There's a sticky bit here around allocators.  Because we're reference counting, there's no guarantee that it will get freed when they call vkDestroyDescriptorSetLayout.  This means that VK_SYSTEM_ALLOCATION_SCOPE_OBJECT is not appropriate.  Instead, we should be using VK_SYSTEM_ALLOCATION_SCOPE_DEVICE and allocating it off the device allocator ignoring pAllocator.  That will probably cause a CTS warning (not an error) in the allocation tests but I think it's the right thing to do.</div><div><br></div><div>Other than that, looks good!<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    set_layout->binding_count = max_binding + 1;<br>
<br>
    for (uint32_t b = 0; b <= max_binding; b++) {<br>
@@ -204,7 +206,8 @@ void anv_<wbr>DestroyDescriptorSetLayout(<br>
    if (!set_layout)<br>
       return;<br>
<br>
-   vk_free2(&device->alloc, pAllocator, set_layout);<br>
+   assert(pAllocator == set_layout->allocator);<br>
+   anv_descriptor_set_layout_<wbr>unref(device, set_layout);<br>
 }<br>
<br>
 static void<br>
@@ -246,6 +249,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 +294,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 +430,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 +462,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 +521,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 b351c6f63b3..d6cf7cff249 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -1199,6 +1199,12 @@ 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>
+   /* Host allocation callback to use when freeing the layout */<br>
+   const VkAllocationCallbacks *allocator;<br>
+<br>
    /* Number of bindings in this descriptor set */<br>
    uint16_t binding_count;<br>
<br>
@@ -1218,6 +1224,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_free2(&device->alloc, layout->allocator, layout);<br>
+}<br>
+<br>
 struct anv_descriptor {<br>
    VkDescriptorType type;<br>
<br>
@@ -1239,7 +1261,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 +1385,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></div>