On Thu, Jan 25, 2018 at 4:24 AM, Iago Toral Quiroga <ito...@igalia.com>
wrote:

> 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."
>
> 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 <ja...@jlekstrand.net>
> ---
>  src/intel/vulkan/anv_cmd_buffer.c     |  6 ++----
>  src/intel/vulkan/anv_descriptor_set.c | 17 ++++++++++++++---
>  src/intel/vulkan/anv_private.h        | 26 ++++++++++++++++++++++++--
>  3 files changed, 40 insertions(+), 9 deletions(-)
>
> diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_
> buffer.c
> index bf80061c6d4..521cf6b6a54 100644
> --- a/src/intel/vulkan/anv_cmd_buffer.c
> +++ b/src/intel/vulkan/anv_cmd_buffer.c
> @@ -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,
> diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_
> descriptor_set.c
> index 1d4df264ae6..99122aed229 100644
> --- a/src/intel/vulkan/anv_descriptor_set.c
> +++ b/src/intel/vulkan/anv_descriptor_set.c
> @@ -67,6 +67,8 @@ VkResult anv_CreateDescriptorSetLayout(
>        return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
>
>     memset(set_layout, 0, sizeof(*set_layout));
> +   set_layout->ref_cnt = 1;
> +   set_layout->allocator = pAllocator;
>

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.

Other than that, looks good!


>     set_layout->binding_count = max_binding + 1;
>
>     for (uint32_t b = 0; b <= max_binding; b++) {
> @@ -204,7 +206,8 @@ void anv_DestroyDescriptorSetLayout(
>     if (!set_layout)
>        return;
>
> -   vk_free2(&device->alloc, pAllocator, set_layout);
> +   assert(pAllocator == set_layout->allocator);
> +   anv_descriptor_set_layout_unref(device, set_layout);
>  }
>
>  static void
> @@ -246,6 +249,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 +294,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 +430,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 +462,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 +521,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 =
> diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_
> private.h
> index b351c6f63b3..d6cf7cff249 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -1199,6 +1199,12 @@ 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;
> +
> +   /* Host allocation callback to use when freeing the layout */
> +   const VkAllocationCallbacks *allocator;
> +
>     /* Number of bindings in this descriptor set */
>     uint16_t binding_count;
>
> @@ -1218,6 +1224,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_free2(&device->alloc, layout->allocator, layout);
> +}
> +
>  struct anv_descriptor {
>     VkDescriptorType type;
>
> @@ -1239,7 +1261,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 +1385,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
> --
> 2.14.1
>
>
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to