[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