<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>