v3dv: don't leak BOs from CLs when using BRANCH
Keep the list of BOs referenced in the CL and free all of them
when the CL is destroyed.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_bo.c b/src/broadcom/vulkan/v3dv_bo.c
index a63e61b..5926ab9 100644
--- a/src/broadcom/vulkan/v3dv_bo.c
+++ b/src/broadcom/vulkan/v3dv_bo.c
@@ -60,6 +60,7 @@
bo->map = NULL;
bo->map_size = 0;
bo->name = name;
+ list_inithead(&bo->list_link);
return bo;
}
diff --git a/src/broadcom/vulkan/v3dv_bo.h b/src/broadcom/vulkan/v3dv_bo.h
index 41337ee..270022d 100644
--- a/src/broadcom/vulkan/v3dv_bo.h
+++ b/src/broadcom/vulkan/v3dv_bo.h
@@ -27,6 +27,8 @@
struct v3dv_device;
struct v3dv_bo {
+ struct list_head list_link;
+
uint32_t handle;
uint32_t size;
uint32_t offset;
diff --git a/src/broadcom/vulkan/v3dv_cl.c b/src/broadcom/vulkan/v3dv_cl.c
index 9aab7b8..c3a9120 100644
--- a/src/broadcom/vulkan/v3dv_cl.c
+++ b/src/broadcom/vulkan/v3dv_cl.c
@@ -32,6 +32,7 @@
cl->bo = NULL;
cl->size = 0;
cl->job = job;
+ list_inithead(&cl->bo_list);
}
void
@@ -52,15 +53,52 @@
void
v3dv_cl_destroy(struct v3dv_cl *cl)
{
- if (cl->bo) {
+ list_for_each_entry_safe(struct v3dv_bo, bo, &cl->bo_list, list_link) {
assert(cl->job);
- v3dv_bo_free(cl->job->device, cl->bo);
+ list_del(&bo->list_link);
+ v3dv_bo_free(cl->job->device, bo);
}
/* Leave the CL in a reset state to catch use after destroy instances */
v3dv_cl_init(NULL, cl);
}
+static bool
+cl_alloc_bo(struct v3dv_cl *cl, uint32_t space, bool use_branch)
+{
+ struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
+ if (!bo) {
+ fprintf(stderr, "failed to allocate memory for command list\n");
+ v3dv_flag_oom(NULL, cl->job);
+ return false;
+ }
+
+ list_addtail(&bo->list_link, &cl->bo_list);
+
+ bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
+ if (!ok) {
+ fprintf(stderr, "failed to map command list buffer\n");
+ v3dv_flag_oom(NULL, cl->job);
+ return false;
+ }
+
+ /* Chain to the new BO from the old one if requested */
+ if (use_branch && cl->bo) {
+ cl_emit(cl, BRANCH, branch) {
+ branch.address = v3dv_cl_address(bo, 0);
+ }
+ }
+
+ v3dv_job_add_bo(cl->job, bo);
+
+ cl->bo = bo;
+ cl->base = cl->bo->map;
+ cl->size = cl->bo->size;
+ cl->next = cl->base;
+
+ return true;
+}
+
uint32_t
v3dv_cl_ensure_space(struct v3dv_cl *cl, uint32_t space, uint32_t alignment)
{
@@ -71,27 +109,7 @@
return offset;
}
- struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
- if (!bo) {
- fprintf(stderr, "failed to allocate memory for command list\n");
- v3dv_flag_oom(NULL, cl->job);
- return 0;
- }
-
- v3dv_job_add_bo(cl->job, bo);
-
- bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
- if (!ok) {
- fprintf(stderr, "failed to map command list buffer\n");
- v3dv_flag_oom(NULL, cl->job);
- return 0;
- }
-
- cl->bo = bo;
- cl->base = cl->bo->map;
- cl->size = cl->bo->size;
- cl->next = cl->base;
-
+ cl_alloc_bo(cl, space, false);
return 0;
}
@@ -101,31 +119,5 @@
if (v3dv_cl_offset(cl) + space + cl_packet_length(BRANCH) <= cl->size)
return;
- struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
- if (!bo) {
- fprintf(stderr, "failed to allocate memory for command list\n");
- v3dv_flag_oom(NULL, cl->job);
- return;
- }
-
- /* Chain to the new BO from the old one if needed */
- if (cl->bo) {
- cl_emit(cl, BRANCH, branch) {
- branch.address = v3dv_cl_address(bo, 0);
- }
- }
-
- v3dv_job_add_bo(cl->job, bo);
-
- bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
- if (!ok) {
- fprintf(stderr, "failed to map command list buffer\n");
- v3dv_flag_oom(NULL, cl->job);
- return;
- }
-
- cl->bo = bo;
- cl->base = cl->bo->map;
- cl->size = cl->bo->size;
- cl->next = cl->base;
+ cl_alloc_bo(cl, space, true);
}
diff --git a/src/broadcom/vulkan/v3dv_cl.h b/src/broadcom/vulkan/v3dv_cl.h
index 03d328c..cd5196c 100644
--- a/src/broadcom/vulkan/v3dv_cl.h
+++ b/src/broadcom/vulkan/v3dv_cl.h
@@ -26,6 +26,8 @@
#include "broadcom/cle/v3d_packet_helpers.h"
+#include "list.h"
+
struct v3dv_bo;
struct v3dv_job;
struct v3dv_cl;
@@ -50,6 +52,7 @@
struct v3dv_cl_out *next;
struct v3dv_bo *bo;
uint32_t size;
+ struct list_head bo_list;
};
static inline struct v3dv_cl_reloc