diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 32d6cbe94c6..7d0a8f9738b 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -2036,6 +2036,90 @@ void si_emit_compute_shader_userdata(struct si_context *sctx) sctx->shader_pointers_dirty &= ~compute_mask; } +/* BINDLESS */ + +struct si_bindless_descriptor_slab +{ + struct pb_slab base; + struct r600_resource *buffer; + struct si_bindless_descriptor *entries; +}; + +bool si_bindless_descriptor_can_reclaim_slab(void *priv, + struct pb_slab_entry *entry) +{ + /* Do not allow to reclaim any bindless descriptors for now because the + * GPU might be using them. This should be improved later on. + */ + return false; +} + +struct pb_slab *si_bindless_descriptor_slab_alloc(void *priv, unsigned heap, + unsigned entry_size, + unsigned group_index) +{ + struct si_context *sctx = priv; + struct si_screen *sscreen = sctx->screen; + struct si_bindless_descriptor_slab *slab; + + slab = CALLOC_STRUCT(si_bindless_descriptor_slab); + if (!slab) + return NULL; + + /* Create a buffer in VRAM for 1024 bindless descriptors. */ + slab->buffer = (struct r600_resource *) + pipe_buffer_create(&sscreen->b.b, 0, + PIPE_USAGE_DEFAULT, 64 * 1024); + if (!slab->buffer) + goto fail; + + slab->base.num_entries = slab->buffer->bo_size / entry_size; + slab->base.num_free = slab->base.num_entries; + slab->entries = CALLOC(slab->base.num_entries, sizeof(*slab->entries)); + if (!slab->entries) + goto fail_buffer; + + LIST_INITHEAD(&slab->base.free); + + for (unsigned i = 0; i < slab->base.num_entries; ++i) { + struct si_bindless_descriptor *desc = &slab->entries[i]; + + desc->entry.slab = &slab->base; + desc->entry.group_index = group_index; + desc->buffer = slab->buffer; + desc->offset = i * entry_size; + + LIST_ADDTAIL(&desc->entry.head, &slab->base.free); + } + + /* Add the descriptor to the per-context list. */ + util_dynarray_append(&sctx->bindless_descriptors, + struct r600_resource *, slab->buffer); + + return &slab->base; + +fail_buffer: + r600_resource_reference(&slab->buffer, NULL); +fail: + FREE(slab); + return NULL; +} + +void si_bindless_descriptor_slab_free(void *priv, struct pb_slab *pslab) +{ + struct si_context *sctx = priv; + struct si_bindless_descriptor_slab *slab = + (struct si_bindless_descriptor_slab *)pslab; + + /* Remove the descriptor from the per-context list. */ + util_dynarray_delete_unordered(&sctx->bindless_descriptors, + struct r600_resource *, slab->buffer); + + r600_resource_reference(&slab->buffer, NULL); + FREE(slab->entries); + FREE(slab); +} + /* INIT/DEINIT/UPLOAD */ /* GFX9 has only 4KB of CE, while previous chips had 32KB. In order diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 031e4731bf0..14fe9dd6a36 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -94,6 +94,9 @@ static void si_destroy_context(struct pipe_context *context) r600_resource_reference(&sctx->last_trace_buf, NULL); radeon_clear_saved_cs(&sctx->last_gfx); + pb_slabs_deinit(&sctx->bindless_descriptor_slabs); + util_dynarray_fini(&sctx->bindless_descriptors); + FREE(sctx); } @@ -316,6 +319,15 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, sctx->tm = si_create_llvm_target_machine(sscreen); + /* Create a slab allocator for all bindless descriptors. */ + if (!pb_slabs_init(&sctx->bindless_descriptor_slabs, 6, 6, 1, sctx, + si_bindless_descriptor_can_reclaim_slab, + si_bindless_descriptor_slab_alloc, + si_bindless_descriptor_slab_free)) + goto fail; + + util_dynarray_init(&sctx->bindless_descriptors, NULL); + return &sctx->b.b; fail: fprintf(stderr, "radeonsi: Failed to create a context.\n"); diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index eef05cf3367..0d8128c88dc 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -28,6 +28,8 @@ #include "si_shader.h" +#include "util/u_dynarray.h" + #ifdef PIPE_ARCH_BIG_ENDIAN #define SI_BIG_ENDIAN 1 #else @@ -228,6 +230,13 @@ union si_vgt_param_key { uint32_t index; }; +struct si_bindless_descriptor +{ + struct pb_slab_entry entry; + struct r600_resource *buffer; + unsigned offset; +}; + struct si_context { struct r600_common_context b; struct blitter_context *blitter; @@ -390,6 +399,12 @@ struct si_context { /* Precomputed IA_MULTI_VGT_PARAM */ union si_vgt_param_key ia_multi_vgt_param_key; unsigned ia_multi_vgt_param[SI_NUM_VGT_PARAM_STATES]; + + /* Slab allocator for bindless descriptors. */ + struct pb_slabs bindless_descriptor_slabs; + + /* Bindless descriptors. */ + struct util_dynarray bindless_descriptors; }; /* cik_sdma.c */ diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h index d8bf13e794a..55227a156b5 100644 --- a/src/gallium/drivers/radeonsi/si_state.h +++ b/src/gallium/drivers/radeonsi/si_state.h @@ -30,6 +30,8 @@ #include "si_pm4.h" #include "radeon/r600_pipe_common.h" +#include "pipebuffer/pb_slab.h" + #define SI_NUM_GRAPHICS_SHADERS (PIPE_SHADER_TESS_EVAL+1) #define SI_NUM_SHADERS (PIPE_SHADER_COMPUTE+1) @@ -340,6 +342,12 @@ void si_set_active_descriptors(struct si_context *sctx, unsigned desc_idx, uint64_t new_active_mask); void si_set_active_descriptors_for_shader(struct si_context *sctx, struct si_shader_selector *sel); +bool si_bindless_descriptor_can_reclaim_slab(void *priv, + struct pb_slab_entry *entry); +struct pb_slab *si_bindless_descriptor_slab_alloc(void *priv, unsigned heap, + unsigned entry_size, + unsigned group_index); +void si_bindless_descriptor_slab_free(void *priv, struct pb_slab *pslab); /* si_state.c */ struct si_shader_selector;