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

Samuel Pitoiset samuel.pitoiset at gmail.com
Fri Aug 4 08:06:06 UTC 2017



On 08/01/2017 09:54 PM, Marek Olšák wrote:
> 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.

Yeah, but we have to keep track of two different arrays. When a texture 
handle is destroyed, the ID can be re-used but not right now, because 
the GPU can still use the descriptor. The names are probably bad, maybe 
bindless_free_slots and bindless_deleted_slots is better?

> 
> 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