radeonsi: support for external buffers (ext_external_objects)
So far, the callback to create a resource from a memory object had code
for importing textures only. Modified it to allow importing buffers too.
Fixes the following piglit tests:
- ext_external_objects/vk-buf-exchange
- ext_external_objects/vk-pix-buf-update-errors
- ext_external_objects/vk-vert-buf-update-errors
- ext_external_objects/vk-vert-buf-reuse
v2: Used si_alloc_buffer_struct instead of CALLOC
v3: Fixed indentation issue, removed free in case of unsuccessful
allocation, joined two if conditions together
Signed-off-by: Eleni Maria Stea <estea@igalia.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6364>
diff --git a/src/gallium/drivers/radeonsi/si_buffer.c b/src/gallium/drivers/radeonsi/si_buffer.c
index 1237074..31f1318 100644
--- a/src/gallium/drivers/radeonsi/si_buffer.c
+++ b/src/gallium/drivers/radeonsi/si_buffer.c
@@ -731,6 +731,39 @@
return &buf->b.b;
}
+struct pipe_resource *si_buffer_from_winsys_buffer(struct pipe_screen *screen,
+ const struct pipe_resource *templ,
+ struct pb_buffer *imported_buf,
+ bool dedicated)
+{
+ struct si_screen *sscreen = (struct si_screen *)screen;
+ struct si_resource *res = si_alloc_buffer_struct(screen, templ);
+
+ if (!res)
+ return 0;
+
+ res->buf = imported_buf;
+ res->gpu_address = sscreen->ws->buffer_get_virtual_address(res->buf);
+ res->bo_size = imported_buf->size;
+ res->bo_alignment = imported_buf->alignment;
+ res->domains = sscreen->ws->buffer_get_initial_domain(res->buf);
+
+ if (res->domains & RADEON_DOMAIN_VRAM)
+ res->vram_usage = res->bo_size;
+ else if (res->domains & RADEON_DOMAIN_GTT)
+ res->gart_usage = res->bo_size;
+
+ if (sscreen->ws->buffer_get_flags)
+ res->flags = sscreen->ws->buffer_get_flags(res->buf);
+
+ if (templ->flags & PIPE_RESOURCE_FLAG_SPARSE) {
+ res->b.b.flags |= SI_RESOURCE_FLAG_UNMAPPABLE;
+ res->flags |= RADEON_FLAG_SPARSE;
+ }
+
+ return &res->b.b;
+}
+
static struct pipe_resource *si_resource_create(struct pipe_screen *screen,
const struct pipe_resource *templ)
{
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 7db1650..6cadec8 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -1926,4 +1926,9 @@
#define PRINT_ERR(fmt, args...) \
fprintf(stderr, "EE %s:%d %s - " fmt, __FILE__, __LINE__, __func__, ##args)
+struct pipe_resource *si_buffer_from_winsys_buffer(struct pipe_screen *screen,
+ const struct pipe_resource *templ,
+ struct pb_buffer *imported_buf,
+ bool dedicated);
+
#endif
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 93e52e7..25b6c38 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -2271,17 +2271,26 @@
free(memobj);
}
-static struct pipe_resource *si_texture_from_memobj(struct pipe_screen *screen,
+static struct pipe_resource *si_resource_from_memobj(struct pipe_screen *screen,
const struct pipe_resource *templ,
struct pipe_memory_object *_memobj,
uint64_t offset)
{
struct si_screen *sscreen = (struct si_screen *)screen;
struct si_memory_object *memobj = (struct si_memory_object *)_memobj;
- struct pipe_resource *tex = si_texture_from_winsys_buffer(
- sscreen, templ, memobj->buf, memobj->stride, offset,
- PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE | PIPE_HANDLE_USAGE_SHADER_WRITE, memobj->b.dedicated);
- if (!tex)
+ struct pipe_resource *res;
+
+ if (templ->target == PIPE_BUFFER)
+ res = si_buffer_from_winsys_buffer(screen, templ, memobj->buf,
+ memobj->b.dedicated);
+ else
+ res = si_texture_from_winsys_buffer(sscreen, templ, memobj->buf,
+ memobj->stride,
+ offset,
+ PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE | PIPE_HANDLE_USAGE_SHADER_WRITE,
+ memobj->b.dedicated);
+
+ if (!res)
return NULL;
/* si_texture_from_winsys_buffer doesn't increment refcount of
@@ -2289,7 +2298,7 @@
*/
struct pb_buffer *buf = NULL;
pb_reference(&buf, memobj->buf);
- return tex;
+ return res;
}
static bool si_check_resource_capability(struct pipe_screen *screen, struct pipe_resource *resource,
@@ -2317,7 +2326,7 @@
sscreen->b.resource_get_handle = si_texture_get_handle;
sscreen->b.resource_get_param = si_resource_get_param;
sscreen->b.resource_get_info = si_texture_get_info;
- sscreen->b.resource_from_memobj = si_texture_from_memobj;
+ sscreen->b.resource_from_memobj = si_resource_from_memobj;
sscreen->b.memobj_create_from_handle = si_memobj_from_handle;
sscreen->b.memobj_destroy = si_memobj_destroy;
sscreen->b.check_resource_capability = si_check_resource_capability;