[Mesa-dev] [PATCH v3 6/6] radeonsi: try to re-use previously deleted bindless descriptor slots

Samuel Pitoiset samuel.pitoiset at gmail.com
Tue Aug 8 16:57:32 UTC 2017


Currently, when the array is full it is resized but it can grow
over and over because we don't try to re-use descriptor slots.

v3: - use new idalloc gallium module

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 src/gallium/drivers/radeonsi/si_descriptors.c | 57 +++++++++++++++++++++------
 src/gallium/drivers/radeonsi/si_pipe.h        |  2 +
 2 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 2e8f1320a1..29eb5bf3d1 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -61,6 +61,7 @@
 #include "gfx9d.h"
 
 #include "util/hash_table.h"
+#include "util/u_idalloc.h"
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_upload_mgr.h"
@@ -2333,33 +2334,62 @@ static void si_init_bindless_descriptors(struct si_context *sctx,
 	 * considered to be a valid handle.
 	 */
 	sctx->num_bindless_descriptors = 1;
+
+	/* Keep track of which bindless slots are used (or not). */
+	util_idalloc_init(&sctx->bindless_used_slots);
+	util_idalloc_resize(&sctx->bindless_used_slots, num_elements);
+
+	/* Lock slot 0 because it's an invalid handle for bindless. */
+	util_idalloc_lock(&sctx->bindless_used_slots, 0);
 }
 
 static inline void si_release_bindless_descriptors(struct si_context *sctx)
 {
 	si_release_descriptors(&sctx->bindless_descriptors);
+	util_idalloc_fini(&sctx->bindless_used_slots);
 }
 
-static unsigned
-si_create_bindless_descriptor(struct si_context *sctx, uint32_t *desc_list,
-			      unsigned size)
+static unsigned si_get_next_free_bindless_slot(struct si_context *sctx)
 {
-	struct si_descriptors *desc = &sctx->bindless_descriptors;
-	unsigned desc_slot, desc_slot_offset;
-
-	/* Reserve a new slot for this bindless descriptor. */
-	desc_slot = sctx->num_bindless_descriptors++;
+	int desc_slot;
 
-	if (desc_slot >= desc->num_elements) {
-		/* The array of bindless descriptors is full, resize it. */
+	desc_slot = util_idalloc_get_next_free(&sctx->bindless_used_slots);
+	if (desc_slot < 0) {
+		/* No slots are available. */
+		struct si_descriptors *desc = &sctx->bindless_descriptors;
 		unsigned slot_size = desc->element_dw_size * 4;
-		unsigned new_num_elements = desc->num_elements * 2;
+		unsigned old_num_elements = desc->num_elements;
+		unsigned new_num_elements = old_num_elements * 2;
 
-		desc->list = REALLOC(desc->list, desc->num_elements * slot_size,
+		/* Resize the array of descriptors. */
+		desc->list = REALLOC(desc->list, old_num_elements * slot_size,
 				     new_num_elements * slot_size);
 		desc->num_elements = new_num_elements;
 		desc->num_active_slots = new_num_elements;
+
+		/* Resize the array of slots. */
+		util_idalloc_resize(&sctx->bindless_used_slots, new_num_elements);
+
+		/* Get a new slot. */
+		desc_slot = util_idalloc_get_next_free(&sctx->bindless_used_slots);
 	}
+	assert(desc_slot);
+
+	/* Prevent this bindless descriptor slot to be re-used. */
+	util_idalloc_lock(&sctx->bindless_used_slots, desc_slot);
+
+	return desc_slot;
+}
+
+static unsigned
+si_create_bindless_descriptor(struct si_context *sctx, uint32_t *desc_list,
+			      unsigned size)
+{
+	struct si_descriptors *desc = &sctx->bindless_descriptors;
+	unsigned desc_slot, desc_slot_offset;
+
+	/* Find a free slot. */
+	desc_slot = si_get_next_free_bindless_slot(sctx);
 
 	/* For simplicity, sampler and image bindless descriptors use fixed
 	 * 16-dword slots for now. Image descriptors only need 8-dword but this
@@ -2473,6 +2503,9 @@ static void si_delete_texture_handle(struct pipe_context *ctx, uint64_t handle)
 
 	tex_handle = (struct si_texture_handle *)entry->data;
 
+	/* Unlock this descriptor slot. */
+	util_idalloc_unlock(&sctx->bindless_used_slots, tex_handle->desc_slot);
+
 	pipe_sampler_view_reference(&tex_handle->view, NULL);
 	_mesa_hash_table_remove(sctx->tex_handles, entry);
 	FREE(tex_handle);
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index c44d6d5dff..447795d97b 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -29,6 +29,7 @@
 #include "si_shader.h"
 
 #include "util/u_dynarray.h"
+#include "util/u_idalloc.h"
 
 #ifdef PIPE_ARCH_BIG_ENDIAN
 #define SI_BIG_ENDIAN 1
@@ -429,6 +430,7 @@ struct si_context {
 
 	/* Bindless descriptors. */
 	struct si_descriptors	bindless_descriptors;
+	struct util_idalloc	bindless_used_slots;
 	unsigned		num_bindless_descriptors;
 	bool			bindless_descriptors_dirty;
 	bool			graphics_bindless_pointer_dirty;
-- 
2.14.0



More information about the mesa-dev mailing list