This implements the Gallium interface. Decompression of resident textures/images will follow in the next patches.
Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> --- src/gallium/drivers/radeonsi/si_descriptors.c | 340 ++++++++++++++++++++++++++ src/gallium/drivers/radeonsi/si_pipe.c | 12 + src/gallium/drivers/radeonsi/si_pipe.h | 26 ++ 3 files changed, 378 insertions(+) diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index abe39de583..a687506f7f 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -60,6 +60,7 @@ #include "sid.h" #include "gfx9d.h" +#include "util/hash_table.h" #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_upload_mgr.h" @@ -2193,6 +2194,339 @@ void si_resident_descriptor_slab_free(void *priv, struct pb_slab *pslab) FREE(slab); } +static int si_add_resident_tex_handle(struct si_context *sctx, + struct si_texture_handle *tex_handle) +{ + int idx; + + /* New resident handle, check if the backing array is large enough. */ + if (sctx->num_resident_tex_handles >= sctx->max_resident_tex_handles) { + unsigned new_max_handles = + MAX2(1, sctx->max_resident_tex_handles * 2); + struct si_texture_handle **new_handles = + REALLOC(sctx->resident_tex_handles, + sctx->num_resident_tex_handles * (sizeof(*new_handles)), + new_max_handles * sizeof(*new_handles)); + + if (new_handles) { + sctx->resident_tex_handles = new_handles; + sctx->max_resident_tex_handles = new_max_handles; + } else { + fprintf(stderr, "si_add_resident_tex_handle: " + "allocation failed\n"); + return -1; + } + } + + idx = sctx->num_resident_tex_handles; + sctx->resident_tex_handles[idx] = tex_handle; + sctx->num_resident_tex_handles++; + + return 0; +} + +static void si_del_resident_tex_handle(struct si_context *sctx, + struct si_texture_handle *tex_handle) +{ + unsigned i; + int size; + + for (i = 0; i < sctx->num_resident_tex_handles; i++) { + if (sctx->resident_tex_handles[i] != tex_handle) + continue; + + if (i < sctx->num_resident_tex_handles - 1) { + size = sizeof(*sctx->resident_tex_handles) * + (sctx->num_resident_tex_handles - 1 - i); + + memmove(&sctx->resident_tex_handles[i], + &sctx->resident_tex_handles[i + 1], size); + } + + sctx->num_resident_tex_handles--; + return; + } +} + +static int si_add_resident_img_handle(struct si_context *sctx, + struct si_image_handle *img_handle) +{ + int idx; + + /* New resident handle, check if the backing array is large enough. */ + if (sctx->num_resident_img_handles >= sctx->max_resident_img_handles) { + unsigned new_max_handles = + MAX2(1, sctx->max_resident_img_handles * 2); + struct si_image_handle **new_handles = + REALLOC(sctx->resident_img_handles, + sctx->num_resident_img_handles * (sizeof(*new_handles)), + new_max_handles * sizeof(*new_handles)); + + if (new_handles) { + sctx->resident_img_handles = new_handles; + sctx->max_resident_img_handles = new_max_handles; + } else { + fprintf(stderr, "si_add_resident_img_handle: " + "allocation failed\n"); + return -1; + } + } + + idx = sctx->num_resident_img_handles; + sctx->resident_img_handles[idx] = img_handle; + sctx->num_resident_img_handles++; + + return 0; +} + +static void si_del_resident_img_handle(struct si_context *sctx, + struct si_image_handle *img_handle) +{ + unsigned i; + int size; + + for (i = 0; i < sctx->num_resident_img_handles; i++) { + if (sctx->resident_img_handles[i] != img_handle) + continue; + + if (i < sctx->num_resident_img_handles - 1) { + size = sizeof(*sctx->resident_img_handles) * + (sctx->num_resident_img_handles - 1 - i); + + memmove(&sctx->resident_img_handles[i], + &sctx->resident_img_handles[i + 1], size); + } + + sctx->num_resident_img_handles--; + return; + } +} + +static struct si_resident_descriptor * +si_create_resident_descriptor(struct si_context *sctx, uint32_t *desc_list, + unsigned size) +{ + struct si_screen *sscreen = sctx->screen; + struct si_resident_descriptor *desc; + struct pb_slab_entry *entry; + void *ptr; + + /* Sub-allocate the resident descriptor from slabs. */ + entry = pb_slab_alloc(&sctx->resident_descriptor_slabs, 64, 0); + if (!entry) + return NULL; + + desc = NULL; + desc = container_of(entry, desc, entry); + + /* Upload the descriptor. */ + ptr = sscreen->b.ws->buffer_map(desc->buffer->buf, NULL, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED); + util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size); + sscreen->b.ws->buffer_unmap(desc->buffer->buf); + + return desc; +} + +static uint64_t si_create_texture_handle(struct pipe_context *ctx, + struct pipe_resource *texture, + struct pipe_sampler_view *view, + const struct pipe_sampler_state *state) +{ + struct si_sampler_view *sview = (struct si_sampler_view *)view; + struct si_context *sctx = (struct si_context *)ctx; + struct si_texture_handle *tex_handle; + struct si_sampler_state *sstate; + uint32_t desc_list[16]; + uint64_t handle; + + tex_handle = CALLOC_STRUCT(si_texture_handle); + if (!tex_handle) + return 0; + + memset(desc_list, 0, sizeof(desc_list)); + si_init_descriptor_list(&desc_list[0], 16, 1, null_texture_descriptor); + + sstate = ctx->create_sampler_state(ctx, state); + if (!sstate) { + FREE(tex_handle); + return 0; + } + + si_set_sampler_view_desc(sctx, sview, sstate, &desc_list[0]); + ctx->delete_sampler_state(ctx, sstate); + + tex_handle->view = sview; + tex_handle->desc = si_create_resident_descriptor(sctx, desc_list, + sizeof(desc_list)); + if (!tex_handle->desc) { + FREE(tex_handle); + return 0; + } + + handle = tex_handle->desc->buffer->gpu_address + + tex_handle->desc->offset; + + if (!_mesa_hash_table_insert(sctx->tex_handles, (void *)handle, + tex_handle)) { + pb_slab_free(&sctx->resident_descriptor_slabs, + &tex_handle->desc->entry); + FREE(tex_handle); + return 0; + } + + return handle; +} + +static void si_delete_texture_handle(struct pipe_context *ctx, uint64_t handle) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct si_texture_handle *tex_handle; + struct hash_entry *entry; + + entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle); + if (!entry) + return; + + tex_handle = (struct si_texture_handle *)entry->data; + + _mesa_hash_table_remove(sctx->tex_handles, entry); + pb_slab_free(&sctx->resident_descriptor_slabs, + &tex_handle->desc->entry); + FREE(tex_handle); +} + +static void si_make_texture_handle_resident(struct pipe_context *ctx, + uint64_t handle, bool resident) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct si_texture_handle *tex_handle; + struct si_sampler_view *sview; + struct hash_entry *entry; + + entry = _mesa_hash_table_search(sctx->tex_handles, (void *)handle); + if (!entry) + return; + + tex_handle = (struct si_texture_handle *)entry->data; + sview = tex_handle->view; + + if (resident) { + si_add_resident_tex_handle(sctx, tex_handle); + + /* Add the buffers to the current CS in case si_begin_new_cs() + * is not going to be called. + */ + radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, + tex_handle->desc->buffer, + RADEON_USAGE_READ, + RADEON_PRIO_DESCRIPTORS); + + si_sampler_view_add_buffer(sctx, sview->base.texture, + RADEON_USAGE_READ, + sview->is_stencil_sampler, false); + } else { + si_del_resident_tex_handle(sctx, tex_handle); + } +} + +static uint64_t si_create_image_handle(struct pipe_context *ctx, + const struct pipe_image_view *view) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct si_image_handle *img_handle; + uint32_t desc_list[16]; + uint64_t handle; + + if (!view || !view->resource) + return 0; + + img_handle = CALLOC_STRUCT(si_image_handle); + if (!img_handle) + return 0; + + memset(desc_list, 0, sizeof(desc_list)); + si_init_descriptor_list(&desc_list[0], 8, 1, null_image_descriptor); + + si_set_shader_image_desc(sctx, view, false, &desc_list[0]); + + util_copy_image_view(&img_handle->view, view); + img_handle->desc = si_create_resident_descriptor(sctx, desc_list, + sizeof(desc_list)); + if (!img_handle->desc) { + FREE(img_handle); + return 0; + } + + handle = img_handle->desc->buffer->gpu_address + + img_handle->desc->offset; + + if (!_mesa_hash_table_insert(sctx->img_handles, (void *)handle, + img_handle)) { + pb_slab_free(&sctx->resident_descriptor_slabs, + &img_handle->desc->entry); + FREE(img_handle); + return 0; + } + + return handle; +} + +static void si_delete_image_handle(struct pipe_context *ctx, uint64_t handle) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct si_image_handle *img_handle; + struct hash_entry *entry; + + entry = _mesa_hash_table_search(sctx->img_handles, (void *)handle); + if (!entry) + return; + + img_handle = (struct si_image_handle *)entry->data; + + _mesa_hash_table_remove(sctx->img_handles, entry); + pb_slab_free(&sctx->resident_descriptor_slabs, + &img_handle->desc->entry); + FREE(img_handle); +} + +static void si_make_image_handle_resident(struct pipe_context *ctx, + uint64_t handle, unsigned access, + bool resident) +{ + struct si_context *sctx = (struct si_context *)ctx; + struct si_image_handle *img_handle; + struct pipe_image_view *view; + struct hash_entry *entry; + + entry = _mesa_hash_table_search(sctx->img_handles, (void *)handle); + if (!entry) + return; + + img_handle = (struct si_image_handle *)entry->data; + view = &img_handle->view; + + if (resident) { + si_add_resident_img_handle(sctx, img_handle); + + /* Add the buffers to the current CS in case si_begin_new_cs() + * is not going to be called. + */ + radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, + img_handle->desc->buffer, + RADEON_USAGE_READ, + RADEON_PRIO_DESCRIPTORS); + + si_sampler_view_add_buffer(sctx, view->resource, + RADEON_USAGE_READWRITE, + false, false); + } else { + si_del_resident_img_handle(sctx, img_handle); + } +} + + /* INIT/DEINIT/UPLOAD */ /* GFX9 has only 4KB of CE, while previous chips had 32KB. In order @@ -2332,6 +2666,12 @@ void si_init_all_descriptors(struct si_context *sctx) sctx->b.b.set_shader_buffers = si_set_shader_buffers; sctx->b.b.set_sampler_views = si_set_sampler_views; sctx->b.b.set_stream_output_targets = si_set_streamout_targets; + sctx->b.b.create_texture_handle = si_create_texture_handle; + sctx->b.b.delete_texture_handle = si_delete_texture_handle; + sctx->b.b.make_texture_handle_resident = si_make_texture_handle_resident; + sctx->b.b.create_image_handle = si_create_image_handle; + sctx->b.b.delete_image_handle = si_delete_image_handle; + sctx->b.b.make_image_handle_resident = si_make_image_handle_resident; sctx->b.invalidate_buffer = si_invalidate_buffer; sctx->b.rebind_buffer = si_rebind_buffer; diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 5b1ddda321..2bb2b3baa7 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -27,6 +27,7 @@ #include "sid.h" #include "radeon/radeon_uvd.h" +#include "util/hash_table.h" #include "util/u_memory.h" #include "util/u_suballoc.h" #include "util/u_tests.h" @@ -96,8 +97,13 @@ static void si_destroy_context(struct pipe_context *context) r600_resource_reference(&sctx->last_trace_buf, NULL); radeon_clear_saved_cs(&sctx->last_gfx); + _mesa_hash_table_destroy(sctx->tex_handles, NULL); + _mesa_hash_table_destroy(sctx->img_handles, NULL); + pb_slabs_deinit(&sctx->resident_descriptor_slabs); + FREE(sctx->resident_tex_handles); + FREE(sctx->resident_img_handles); FREE(sctx->resident_descriptors); FREE(sctx); } @@ -324,6 +330,12 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, si_resident_descriptor_slab_free)) goto fail; + /* Bindless handles. */ + sctx->tex_handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + sctx->img_handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + 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 41b0a2a79f..3a2487bff0 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -231,6 +231,18 @@ struct si_resident_descriptor unsigned offset; }; +struct si_texture_handle +{ + struct si_resident_descriptor *desc; + struct si_sampler_view *view; +}; + +struct si_image_handle +{ + struct si_resident_descriptor *desc; + struct pipe_image_view view; +}; + struct si_context { struct r600_common_context b; struct blitter_context *blitter; @@ -399,6 +411,20 @@ struct si_context { struct r600_resource **resident_descriptors; unsigned num_resident_descriptors; unsigned max_resident_descriptors; + + /* Allocatd bindless handles */ + struct hash_table *tex_handles; + struct hash_table *img_handles; + + /* Resident texture handles */ + struct si_texture_handle **resident_tex_handles; + unsigned num_resident_tex_handles; + unsigned max_resident_tex_handles; + + /* Resident image handles */ + struct si_image_handle **resident_img_handles; + unsigned num_resident_img_handles; + unsigned max_resident_img_handles; }; /* cik_sdma.c */ -- 2.13.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev