[Mesa-dev] [PATCH v2 52/64] radeonsi: implement ARB_bindless_texture
Samuel Pitoiset
samuel.pitoiset at gmail.com
Tue May 30 20:36:23 UTC 2017
This implements the Gallium interface. Decompression of resident
textures/images will follow in the next patches.
v2: - fix a memleak related to util_copy_image_view()
- remove "texture" parameter from create_texture_handle()
- store pipe_sampler_view instead of si_sampler_view
- make use pipe_sampler_view_reference() to fix a refcount issue
- rename si_resident_descriptor to si_bindless_descriptor
- use util_dynarray_*
- add more comments
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
src/gallium/drivers/radeonsi/si_descriptors.c | 249 ++++++++++++++++++++++++++
src/gallium/drivers/radeonsi/si_pipe.c | 15 ++
src/gallium/drivers/radeonsi/si_pipe.h | 20 +++
3 files changed, 284 insertions(+)
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index b2e2e4b760..238cca4561 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"
@@ -2130,6 +2131,248 @@ void si_bindless_descriptor_slab_free(void *priv, struct pb_slab *pslab)
FREE(slab);
}
+static struct si_bindless_descriptor *
+si_create_bindless_descriptor(struct si_context *sctx, uint32_t *desc_list,
+ unsigned size)
+{
+ struct si_screen *sscreen = sctx->screen;
+ struct si_bindless_descriptor *desc;
+ struct pb_slab_entry *entry;
+ void *ptr;
+
+ /* Sub-allocate the bindless descriptor from a slab to avoid dealing
+ * with a ton of buffers and for reducing the winsys overhead.
+ */
+ entry = pb_slab_alloc(&sctx->bindless_descriptor_slabs, 64, 0);
+ if (!entry)
+ return NULL;
+
+ desc = NULL;
+ desc = container_of(entry, desc, entry);
+
+ /* Upload the descriptor directly in VRAM. Because the slabs are
+ * currentlyu never reclaimed, we don't need to synchronize the
+ * operation.
+ */
+ 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_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->desc = si_create_bindless_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->bindless_descriptor_slabs,
+ &tex_handle->desc->entry);
+ FREE(tex_handle);
+ return 0;
+ }
+
+ pipe_sampler_view_reference(&tex_handle->view, view);
+
+ 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;
+
+ pipe_sampler_view_reference(&tex_handle->view, NULL);
+ _mesa_hash_table_remove(sctx->tex_handles, entry);
+ pb_slab_free(&sctx->bindless_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 = (struct si_sampler_view *)tex_handle->view;
+
+ if (resident) {
+ /* Add the texture handle to the per-context list. */
+ util_dynarray_append(&sctx->resident_tex_handles,
+ struct si_texture_handle *, 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 {
+ /* Remove the texture handle from the per-context list. */
+ util_dynarray_delete(&sctx->resident_tex_handles,
+ struct si_texture_handle *, 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]);
+
+ img_handle->desc = si_create_bindless_descriptor(sctx, desc_list,
+ sizeof(desc_list));
+ if (!img_handle->desc) {
+ util_copy_image_view(&img_handle->view, NULL);
+ 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->bindless_descriptor_slabs,
+ &img_handle->desc->entry);
+ FREE(img_handle);
+ return 0;
+ }
+
+ util_copy_image_view(&img_handle->view, view);
+
+ 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;
+
+ util_copy_image_view(&img_handle->view, NULL);
+ _mesa_hash_table_remove(sctx->img_handles, entry);
+ pb_slab_free(&sctx->bindless_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) {
+ /* Add the image handle to the per-context list. */
+ util_dynarray_append(&sctx->resident_img_handles,
+ struct si_image_handle *, 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 {
+ /* Remove the image handle from the per-context list. */
+ util_dynarray_delete(&sctx->resident_img_handles,
+ struct si_image_handle *, img_handle);
+ }
+}
+
+
/* INIT/DEINIT/UPLOAD */
/* GFX9 has only 4KB of CE, while previous chips had 32KB. In order
@@ -2269,6 +2512,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 5e6c745f96..b8f9ed23fd 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"
@@ -97,6 +98,11 @@ static void si_destroy_context(struct pipe_context *context)
pb_slabs_deinit(&sctx->bindless_descriptor_slabs);
util_dynarray_fini(&sctx->bindless_descriptors);
+ _mesa_hash_table_destroy(sctx->tex_handles, NULL);
+ _mesa_hash_table_destroy(sctx->img_handles, NULL);
+
+ util_dynarray_fini(&sctx->resident_tex_handles);
+ util_dynarray_fini(&sctx->resident_img_handles);
FREE(sctx);
}
@@ -328,6 +334,15 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen,
util_dynarray_init(&sctx->bindless_descriptors);
+ /* 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);
+
+ util_dynarray_init(&sctx->resident_tex_handles);
+ util_dynarray_init(&sctx->resident_img_handles);
+
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 2e7b183504..8b7ff26a69 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -233,6 +233,18 @@ struct si_bindless_descriptor
unsigned offset;
};
+struct si_texture_handle
+{
+ struct si_bindless_descriptor *desc;
+ struct pipe_sampler_view *view;
+};
+
+struct si_image_handle
+{
+ struct si_bindless_descriptor *desc;
+ struct pipe_image_view view;
+};
+
struct si_context {
struct r600_common_context b;
struct blitter_context *blitter;
@@ -399,6 +411,14 @@ struct si_context {
/* Bindless descriptors. */
struct util_dynarray bindless_descriptors;
+
+ /* Allocated bindless handles */
+ struct hash_table *tex_handles;
+ struct hash_table *img_handles;
+
+ /* Resident bindless handles */
+ struct util_dynarray resident_tex_handles;
+ struct util_dynarray resident_img_handles;
};
/* cik_sdma.c */
--
2.13.0
More information about the mesa-dev
mailing list