Hi Samuel, Can you move this slot allocator into a util module? It seems generic enough that it could be reused for "handle" and "ID" allocations.
Some additional notes: - a bit array of uin32_t would be better. bool is too large (1 byte). - "free" is the inverse of "used", so the "used" array is redundant. Thanks, Marek On Wed, Jul 26, 2017 at 4:21 PM, Samuel Pitoiset <samuel.pitoi...@gmail.com> wrote: > 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. > > The idea is to maintain two simple lists which keep track of > which slots is used and which ones have been deleted. When the > array is resized, previously deleted slots can be marked as > free because we are going to upload a new fresh buffer. > > Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> > --- > src/gallium/drivers/radeonsi/si_descriptors.c | 85 > +++++++++++++++++++++++---- > src/gallium/drivers/radeonsi/si_pipe.h | 2 + > 2 files changed, 75 insertions(+), 12 deletions(-) > > diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c > b/src/gallium/drivers/radeonsi/si_descriptors.c > index 543a19ba1e..95f0479be7 100644 > --- a/src/gallium/drivers/radeonsi/si_descriptors.c > +++ b/src/gallium/drivers/radeonsi/si_descriptors.c > @@ -2299,11 +2299,72 @@ static void si_init_bindless_descriptors(struct > si_context *sctx, > * considered to be a valid handle. > */ > sctx->num_bindless_descriptors = 1; > + > + /* Allocate two simple arrays for re-using previously deleted slots. > */ > + sctx->bindless_used_slots = CALLOC(num_elements, sizeof(bool)); > + sctx->bindless_free_slots = CALLOC(num_elements, sizeof(bool)); > } > > static inline void si_release_bindless_descriptors(struct si_context *sctx) > { > si_release_descriptors(&sctx->bindless_descriptors); > + FREE(sctx->bindless_used_slots); > + FREE(sctx->bindless_free_slots); > +} > + > +static unsigned si_get_next_free_bindless_slot(struct si_context *sctx) > +{ > + struct si_descriptors *desc = &sctx->bindless_descriptors; > + unsigned i; > + > + for (i = 1; i < desc->num_elements; i++) { > + if (!sctx->bindless_used_slots[i]) { > + /* Lock this descriptor slot. */ > + sctx->bindless_used_slots[i] = true; > + return i; > + } > + } > + > + /* No available descriptor slots. */ > + return 0; > +} > + > +static void si_resize_bindless_descriptor(struct si_context *sctx) > +{ > + struct si_descriptors *desc = &sctx->bindless_descriptors; > + unsigned slot_size = desc->element_dw_size * 4; > + unsigned old_num_elements = desc->num_elements; > + unsigned new_num_elements = old_num_elements * 2; > + unsigned i; > + > + /* All previously deleted slots can now be re-used because we are > going > + * to upload a new buffer. > + */ > + for (i = 1; i < old_num_elements; i++) { > + if (sctx->bindless_free_slots[i]) { > + /* Unlock this descriptor slot. */ > + sctx->bindless_used_slots[i] = false; > + } > + sctx->bindless_free_slots[i] = false; > + } > + > + /* Resize the array of descriptors. */ > + desc->list = REALLOC(desc->list, desc->num_elements * slot_size, > + new_num_elements * slot_size); > + desc->num_elements = new_num_elements; > + desc->num_active_slots = new_num_elements; > + > + /* Resize the two simple arrays and mark all slots as free. */ > + sctx->bindless_used_slots = REALLOC(sctx->bindless_used_slots, > + old_num_elements, > + new_num_elements); > + sctx->bindless_free_slots = REALLOC(sctx->bindless_free_slots, > + old_num_elements, > + new_num_elements); > + for (i = old_num_elements; i < new_num_elements; i++) { > + sctx->bindless_used_slots[i] = false; > + sctx->bindless_free_slots[i] = false; > + } > } > > static unsigned > @@ -2315,19 +2376,16 @@ si_create_bindless_descriptor(struct si_context > *sctx, uint32_t *desc_list, > unsigned desc_slot, desc_slot_offset; > bool resized = false; > > - /* Reserve a new slot for this bindless descriptor. */ > - desc_slot = sctx->num_bindless_descriptors++; > - > - if (desc_slot >= desc->num_elements) { > - /* The array of bindless descriptors is full, resize it. */ > - unsigned slot_size = desc->element_dw_size * 4; > - unsigned new_num_elements = desc->num_elements * 2; > - > - desc->list = REALLOC(desc->list, desc->num_elements * > slot_size, > - new_num_elements * slot_size); > - desc->num_elements = new_num_elements; > - desc->num_active_slots = new_num_elements; > + /* Find a free slot. */ > + desc_slot = si_get_next_free_bindless_slot(sctx); > + if (!desc_slot) { > + /* The array of descriptors is full, resize it. */ > + si_resize_bindless_descriptor(sctx); > resized = true; > + > + /* Get a new slot. */ > + desc_slot = si_get_next_free_bindless_slot(sctx); > + assert(desc_slot); > } > > /* For simplicity, sampler and image bindless descriptors use fixed > @@ -2459,6 +2517,9 @@ static void si_delete_texture_handle(struct > pipe_context *ctx, uint64_t handle) > > tex_handle = (struct si_texture_handle *)entry->data; > > + /* Mark this descriptor slot as free in order to re-use it. */ > + sctx->bindless_free_slots[tex_handle->desc_slot] = true; > + > 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 cfdf4a5571..c79be578f9 100644 > --- a/src/gallium/drivers/radeonsi/si_pipe.h > +++ b/src/gallium/drivers/radeonsi/si_pipe.h > @@ -414,6 +414,8 @@ struct si_context { > > /* Bindless descriptors. */ > struct si_descriptors bindless_descriptors; > + bool *bindless_used_slots; > + bool *bindless_free_slots; > unsigned num_bindless_descriptors; > bool bindless_descriptors_dirty; > bool graphics_bindless_pointer_dirty; > -- > 2.13.3 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev