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;