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

Reply via email to