v3dv: ref/unref pipeline layout objects

Since KHR_maintenance4 it is possible to destroy pipeline layouts
immediately after creating pipelines.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18246>
diff --git a/src/broadcom/vulkan/v3dv_descriptor_set.c b/src/broadcom/vulkan/v3dv_descriptor_set.c
index dc5baae..52edcf1 100644
--- a/src/broadcom/vulkan/v3dv_descriptor_set.c
+++ b/src/broadcom/vulkan/v3dv_descriptor_set.c
@@ -339,6 +339,7 @@
       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
 
    layout->num_sets = pCreateInfo->setLayoutCount;
+   layout->ref_cnt = 1;
 
    uint32_t dynamic_offset_count = 0;
    for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
@@ -405,7 +406,7 @@
    if (!pipeline_layout)
       return;
 
-   v3dv_pipeline_layout_destroy(device, pipeline_layout, pAllocator);
+   v3dv_pipeline_layout_unref(device, pipeline_layout, pAllocator);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL
diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c
index 3d35396..b9493ab 100644
--- a/src/broadcom/vulkan/v3dv_pipeline.c
+++ b/src/broadcom/vulkan/v3dv_pipeline.c
@@ -150,6 +150,9 @@
    if (pipeline->executables.mem_ctx)
       ralloc_free(pipeline->executables.mem_ctx);
 
+   if (pipeline->layout)
+      v3dv_pipeline_layout_unref(device, pipeline->layout, pAllocator);
+
    vk_object_free(&device->vk, pAllocator, pipeline);
 }
 
@@ -3025,6 +3028,8 @@
    /* This must be done after the pipeline has been compiled */
    pipeline_set_ez_state(pipeline, ds_info);
 
+   v3dv_pipeline_layout_ref(pipeline->layout);
+
    return result;
 }
 
@@ -3265,6 +3270,10 @@
    pipeline->layout = layout;
 
    VkResult result = pipeline_compile_compute(pipeline, cache, info, alloc);
+   if (result != VK_SUCCESS)
+      return result;
+
+   v3dv_pipeline_layout_ref(pipeline->layout);
 
    return result;
 }
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 29c5c5d..8de3cc2 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1842,6 +1842,11 @@
    uint32_t dynamic_offset_count;
    uint32_t push_constant_size;
 
+   /* Pipeline layouts can be destroyed after creating pipelines since
+    * maintenance4.
+    */
+   uint32_t ref_cnt;
+
    unsigned char sha1[20];
 };
 
@@ -1850,6 +1855,23 @@
                              struct v3dv_pipeline_layout *layout,
                              const VkAllocationCallbacks *alloc);
 
+static inline void
+v3dv_pipeline_layout_ref(struct v3dv_pipeline_layout *layout)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   p_atomic_inc(&layout->ref_cnt);
+}
+
+static inline void
+v3dv_pipeline_layout_unref(struct v3dv_device *device,
+                           struct v3dv_pipeline_layout *layout,
+                           const VkAllocationCallbacks *alloc)
+{
+   assert(layout && layout->ref_cnt >= 1);
+   if (p_atomic_dec_zero(&layout->ref_cnt))
+      v3dv_pipeline_layout_destroy(device, layout, alloc);
+}
+
 /*
  * We are using descriptor maps for ubo/ssbo and texture/samplers, so we need
  * it to be big enough to include the max value for all of them.