[Mesa-dev] [PATCH v2 6/6] radeonsi: try to re-use previously deleted bindless descriptor slots
Marek Olšák
maraeo at gmail.com
Tue Aug 1 19:54:30 UTC 2017
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.pitoiset at 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.pitoiset at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list