[Mesa-dev] [PATCH v2 52/64] radeonsi: implement ARB_bindless_texture

Nicolai Hähnle nhaehnle at gmail.com
Fri Jun 9 07:29:35 UTC 2017


On 30.05.2017 22:36, Samuel Pitoiset wrote:
> 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

Typo: *currently

Cheers,
Nicolai


> +	 * 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 */
> 


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list