lavapipe: add reference counting to descriptor set layout
authorDave Airlie <airlied@redhat.com>
Tue, 9 Feb 2021 03:44:58 +0000 (13:44 +1000)
committerMarge Bot <eric+marge@anholt.net>
Thu, 18 Feb 2021 01:07:32 +0000 (01:07 +0000)
asan flagged some use after frees, copy the anv solution
of refcounting the descriptor set layout objects.

dEQP-VK.api.descriptor_set.descriptor_set_layout_lifetime.*

Acked-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9093>

src/gallium/frontends/lavapipe/lvp_descriptor_set.c
src/gallium/frontends/lavapipe/lvp_private.h

index 172dde714621a1c8550798333e2d1dc22d145ece..0703d32a24190249ec019cebc62a658c8f929c21 100644 (file)
@@ -54,6 +54,7 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout(
 
    vk_object_base_init(&device->vk, &set_layout->base,
                        VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
+   set_layout->ref_cnt = 1;
    /* We just allocate all the samplers at the end of the struct */
    struct lvp_sampler **samplers =
       (struct lvp_sampler **)&set_layout->binding[max_binding + 1];
@@ -156,6 +157,15 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout(
    return VK_SUCCESS;
 }
 
+void
+lvp_descriptor_set_layout_destroy(struct lvp_device *device,
+                                  struct lvp_descriptor_set_layout *layout)
+{
+   assert(layout->ref_cnt == 0);
+   vk_object_base_finish(&layout->base);
+   vk_free(&device->vk.alloc, layout);
+}
+
 VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorSetLayout(
     VkDevice                                    _device,
     VkDescriptorSetLayout                       _set_layout,
@@ -166,8 +176,8 @@ VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorSetLayout(
 
    if (!_set_layout)
      return;
-   vk_object_base_finish(&set_layout->base);
-   vk_free2(&device->vk.alloc, pAllocator, set_layout);
+
+   lvp_descriptor_set_layout_unref(device, set_layout);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePipelineLayout(
@@ -194,6 +204,7 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePipelineLayout(
       LVP_FROM_HANDLE(lvp_descriptor_set_layout, set_layout,
                       pCreateInfo->pSetLayouts[set]);
       layout->set[set].layout = set_layout;
+      lvp_descriptor_set_layout_ref(set_layout);
    }
 
    layout->push_constant_size = 0;
@@ -218,13 +229,16 @@ VKAPI_ATTR void VKAPI_CALL lvp_DestroyPipelineLayout(
 
    if (!_pipelineLayout)
      return;
+   for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
+      lvp_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
+
    vk_object_base_finish(&pipeline_layout->base);
    vk_free2(&device->vk.alloc, pAllocator, pipeline_layout);
 }
 
 VkResult
 lvp_descriptor_set_create(struct lvp_device *device,
-                          const struct lvp_descriptor_set_layout *layout,
+                          struct lvp_descriptor_set_layout *layout,
                           struct lvp_descriptor_set **out_set)
 {
    struct lvp_descriptor_set *set;
@@ -243,6 +257,7 @@ lvp_descriptor_set_create(struct lvp_device *device,
    vk_object_base_init(&device->vk, &set->base,
                        VK_OBJECT_TYPE_DESCRIPTOR_SET);
    set->layout = layout;
+   lvp_descriptor_set_layout_ref(layout);
 
    /* Go through and fill out immutable samplers if we have any */
    struct lvp_descriptor *desc = set->descriptors;
@@ -263,6 +278,7 @@ void
 lvp_descriptor_set_destroy(struct lvp_device *device,
                            struct lvp_descriptor_set *set)
 {
+   lvp_descriptor_set_layout_unref(device, set->layout);
    vk_object_base_finish(&set->base);
    vk_free(&device->vk.alloc, set);
 }
@@ -460,6 +476,7 @@ static void lvp_reset_descriptor_pool(struct lvp_device *device,
 {
    struct lvp_descriptor_set *set, *tmp;
    LIST_FOR_EACH_ENTRY_SAFE(set, tmp, &pool->sets, link) {
+      lvp_descriptor_set_layout_unref(device, set->layout);
       list_del(&set->link);
       vk_free(&device->vk.alloc, set);
    }
index 9439859ddb20b141039f9f69390d000f4c4f9fe2..57a270c5fa201eb3c653dfe149a689b0c98418e1 100644 (file)
@@ -416,6 +416,10 @@ struct lvp_descriptor_set_binding_layout {
 
 struct lvp_descriptor_set_layout {
    struct vk_object_base base;
+
+   /* 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;
 
@@ -440,6 +444,25 @@ struct lvp_descriptor_set_layout {
    struct lvp_descriptor_set_binding_layout binding[0];
 };
 
+void lvp_descriptor_set_layout_destroy(struct lvp_device *device,
+                                       struct lvp_descriptor_set_layout *layout);
+
+static inline void
+lvp_descriptor_set_layout_ref(struct lvp_descriptor_set_layout *layout)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   p_atomic_inc(&layout->ref_cnt);
+}
+
+static inline void
+lvp_descriptor_set_layout_unref(struct lvp_device *device,
+                                struct lvp_descriptor_set_layout *layout)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   if (p_atomic_dec_zero(&layout->ref_cnt))
+      lvp_descriptor_set_layout_destroy(device, layout);
+}
+
 union lvp_descriptor_info {
    struct {
       struct lvp_sampler *sampler;
@@ -462,7 +485,7 @@ struct lvp_descriptor {
 
 struct lvp_descriptor_set {
    struct vk_object_base base;
-   const struct lvp_descriptor_set_layout *layout;
+   struct lvp_descriptor_set_layout *layout;
    struct list_head link;
    struct lvp_descriptor descriptors[0];
 };
@@ -488,7 +511,7 @@ struct lvp_descriptor_update_template {
 
 VkResult
 lvp_descriptor_set_create(struct lvp_device *device,
-                          const struct lvp_descriptor_set_layout *layout,
+                          struct lvp_descriptor_set_layout *layout,
                           struct lvp_descriptor_set **out_set);
 
 void