v3dv: add framework for private driver objects

This allows the driver to register private Vulkan objects it creates as part
of command  buffer recording (usually for meta operations) in the command
buffer, so they can be destroyed together with it.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index aacf554..7192a0f 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -122,6 +122,7 @@
    cmd_buffer->pool = pool;
    cmd_buffer->level = level;
 
+   list_inithead(&cmd_buffer->private_objs);
    list_inithead(&cmd_buffer->submit_jobs);
 
    assert(pool);
@@ -190,6 +191,37 @@
    vk_free(&job->device->alloc, job);
 }
 
+void
+v3dv_cmd_buffer_add_private_obj(struct v3dv_cmd_buffer *cmd_buffer,
+                                void *obj,
+                                v3dv_cmd_buffer_private_obj_destroy_cb destroy_cb)
+{
+   struct v3dv_cmd_buffer_private_obj *pobj =
+      vk_alloc(&cmd_buffer->device->alloc, sizeof(*pobj), 8,
+               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!pobj) {
+      cmd_buffer->state.oom = true;
+      return;
+   }
+
+   pobj->obj = obj;
+   pobj->destroy_cb = destroy_cb;
+
+   list_addtail(&pobj->list_link, &cmd_buffer->private_objs);
+}
+
+static void
+cmd_buffer_destroy_private_obj(struct v3dv_cmd_buffer *cmd_buffer,
+                               struct v3dv_cmd_buffer_private_obj *pobj)
+{
+   assert(pobj && pobj->obj && pobj->destroy_cb);
+   pobj->destroy_cb(v3dv_device_to_handle(cmd_buffer->device),
+                    pobj->obj,
+                    &cmd_buffer->device->alloc);
+   list_del(&pobj->list_link);
+   vk_free(&cmd_buffer->device->alloc, pobj);
+}
+
 static void
 cmd_buffer_free_resources(struct v3dv_cmd_buffer *cmd_buffer)
 {
@@ -213,6 +245,11 @@
 
    if (cmd_buffer->push_constants_resource.bo)
       v3dv_bo_free(cmd_buffer->device, cmd_buffer->push_constants_resource.bo);
+
+   list_for_each_entry_safe(struct v3dv_cmd_buffer_private_obj, pobj,
+                            &cmd_buffer->private_objs, list_link) {
+      cmd_buffer_destroy_private_obj(cmd_buffer, pobj);
+   }
 }
 
 static void
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 7a0c0fa..e94b4be 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -851,6 +851,15 @@
                                          VkDeviceSize stride,
                                          VkQueryResultFlags flags);
 
+typedef void (*v3dv_cmd_buffer_private_obj_destroy_cb)(VkDevice device,
+                                                       void *pobj,
+                                                       VkAllocationCallbacks *alloc);
+struct v3dv_cmd_buffer_private_obj {
+   struct list_head list_link;
+   void *obj;
+   v3dv_cmd_buffer_private_obj_destroy_cb destroy_cb;
+};
+
 struct v3dv_cmd_buffer {
    VK_LOADER_DATA _loader_data;
 
@@ -869,6 +878,12 @@
    uint32_t push_constants_data[MAX_PUSH_CONSTANTS_SIZE / 4];
    struct v3dv_resource push_constants_resource;
 
+   /* Collection of Vulkan objects created internally by the driver (typically
+    * during recording of meta operations) that are part of the command buffer
+    * and should be destroyed with it.
+    */
+   struct list_head private_objs; /* v3dv_cmd_buffer_private_obj */
+
    /* List of jobs to submit to the kernel */
    struct list_head submit_jobs;
 };
@@ -921,6 +936,10 @@
 void v3dv_cmd_buffer_add_tfu_job(struct v3dv_cmd_buffer *cmd_buffer,
                                  struct drm_v3d_submit_tfu *tfu);
 
+void v3dv_cmd_buffer_add_private_obj(struct v3dv_cmd_buffer *cmd_buffer,
+                                     void *obj,
+                                     v3dv_cmd_buffer_private_obj_destroy_cb destroy_cb);
+
 struct v3dv_semaphore {
    /* A syncobject handle associated with this semaphore */
    uint32_t sync;