From 81b0840caaa9d80560a779b7195778b95e34c0ad Mon Sep 17 00:00:00 2001 From: Julia Tatz Date: Wed, 24 May 2023 19:51:29 -0400 Subject: [PATCH] zink: Implement PIPE_CAP_RESOURCE_FROM_USER_MEMORY Needed for GL_AMD_pinned_memory & zero-copy support in opencl Part-of: --- src/gallium/drivers/zink/zink_device_info.py | 1 + src/gallium/drivers/zink/zink_resource.c | 56 ++++++++++++++++---- src/gallium/drivers/zink/zink_screen.c | 2 + 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 06062ee7e03..f6b699a478e 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -84,6 +84,7 @@ EXTENSIONS = [ Extension("VK_KHR_buffer_device_address", alias="bda", features=True), + Extension("VK_EXT_external_memory_host", alias="ext_host_mem", properties=True), Extension("VK_EXT_queue_family_foreign"), Extension("VK_KHR_swapchain_mutable_format"), Extension("VK_EXT_provoking_vertex", diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 04962ae7017..8cf5304c923 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -603,7 +603,7 @@ retry: static struct zink_resource_object * resource_object_create(struct zink_screen *screen, const struct pipe_resource *templ, struct winsys_handle *whandle, bool *linear, - uint64_t *modifiers, int modifiers_count, const void *loader_private) + uint64_t *modifiers, int modifiers_count, const void *loader_private, const void *user_mem) { struct zink_resource_object *obj = CALLOC_STRUCT(zink_resource_object); unsigned max_level = 0; @@ -985,6 +985,20 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t if (templ->bind & ZINK_BIND_TRANSIENT) flags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + if (user_mem) { + VkExternalMemoryHandleTypeFlagBits handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + VkMemoryHostPointerPropertiesEXT memory_host_pointer_properties = {0}; + memory_host_pointer_properties.sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT; + memory_host_pointer_properties.pNext = NULL; + VkResult res = VKSCR(GetMemoryHostPointerPropertiesEXT)(screen->dev, handle_type, user_mem, &memory_host_pointer_properties); + if (res != VK_SUCCESS) { + mesa_loge("ZINK: vkGetMemoryHostPointerPropertiesEXT failed"); + goto fail1; + } + reqs.memoryTypeBits &= memory_host_pointer_properties.memoryTypeBits; + flags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + VkMemoryAllocateInfo mai; enum zink_alloc_flag aflags = templ->flags & PIPE_RESOURCE_FLAG_SPARSE ? ZINK_ALLOC_SPARSE : 0; mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -1062,6 +1076,17 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t #endif + VkImportMemoryHostPointerInfoEXT imhpi = { + VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, + NULL, + }; + if (user_mem) { + imhpi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + imhpi.pHostPointer = (void*)user_mem; + imhpi.pNext = mai.pNext; + mai.pNext = &imhpi; + } + unsigned alignment = MAX2(reqs.alignment, 256); if (templ->usage == PIPE_USAGE_STAGING && obj->is_buffer) alignment = MAX2(alignment, screen->info.props.limits.minMemoryMapAlignment); @@ -1178,7 +1203,7 @@ resource_create(struct pipe_screen *pscreen, struct winsys_handle *whandle, unsigned external_usage, const uint64_t *modifiers, int modifiers_count, - const void *loader_private) + const void *loader_private, const void *user_mem) { struct zink_screen *screen = zink_screen(pscreen); struct zink_resource *res = CALLOC_STRUCT_CL(zink_resource); @@ -1214,7 +1239,7 @@ resource_create(struct pipe_screen *pscreen, templ2.flags &= ~PIPE_RESOURCE_FLAG_SPARSE; res->base.b.flags &= ~PIPE_RESOURCE_FLAG_SPARSE; } - res->obj = resource_object_create(screen, &templ2, whandle, &linear, res->modifiers, res->modifiers_count, loader_private); + res->obj = resource_object_create(screen, &templ2, whandle, &linear, res->modifiers, res->modifiers_count, loader_private, user_mem); if (!res->obj) { free(res->modifiers); FREE_CL(res); @@ -1325,14 +1350,14 @@ static struct pipe_resource * zink_resource_create(struct pipe_screen *pscreen, const struct pipe_resource *templ) { - return resource_create(pscreen, templ, NULL, 0, NULL, 0, NULL); + return resource_create(pscreen, templ, NULL, 0, NULL, 0, NULL, NULL); } static struct pipe_resource * zink_resource_create_with_modifiers(struct pipe_screen *pscreen, const struct pipe_resource *templ, const uint64_t *modifiers, int modifiers_count) { - return resource_create(pscreen, templ, NULL, 0, modifiers, modifiers_count, NULL); + return resource_create(pscreen, templ, NULL, 0, modifiers, modifiers_count, NULL, NULL); } static struct pipe_resource * @@ -1340,7 +1365,7 @@ zink_resource_create_drawable(struct pipe_screen *pscreen, const struct pipe_resource *templ, const void *loader_private) { - return resource_create(pscreen, templ, NULL, 0, NULL, 0, loader_private); + return resource_create(pscreen, templ, NULL, 0, NULL, 0, loader_private, NULL); } static bool @@ -1360,7 +1385,7 @@ add_resource_bind(struct zink_context *ctx, struct zink_resource *res, unsigned res->modifiers[0] = DRM_FORMAT_MOD_LINEAR; } - struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, &res->linear, res->modifiers, res->modifiers_count, NULL); + struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, &res->linear, res->modifiers, res->modifiers_count, NULL, NULL); if (!new_obj) { debug_printf("new backing resource alloc failed!\n"); res->base.b.bind &= ~bind; @@ -1610,7 +1635,7 @@ zink_resource_from_handle(struct pipe_screen *pscreen, modifier = whandle->modifier; modifier_count = 1; } - struct pipe_resource *pres = resource_create(pscreen, &templ2, whandle, usage, &modifier, modifier_count, NULL); + struct pipe_resource *pres = resource_create(pscreen, &templ2, whandle, usage, &modifier, modifier_count, NULL, NULL); if (pres) { struct zink_resource *res = zink_resource(pres); if (pres->target != PIPE_BUFFER) @@ -1625,6 +1650,14 @@ zink_resource_from_handle(struct pipe_screen *pscreen, #endif } +static struct pipe_resource * +zink_resource_from_user_memory(struct pipe_screen *pscreen, + const struct pipe_resource *templ, + void *user_memory) +{ + return resource_create(pscreen, templ, NULL, 0, NULL, 0, NULL, user_memory); +} + struct zink_memory_object { struct pipe_memory_object b; struct winsys_handle whandle; @@ -1680,7 +1713,7 @@ zink_resource_from_memobj(struct pipe_screen *pscreen, { struct zink_memory_object *memobj = (struct zink_memory_object *)pmemobj; - struct pipe_resource *pres = resource_create(pscreen, templ, &memobj->whandle, 0, NULL, 0, NULL); + struct pipe_resource *pres = resource_create(pscreen, templ, &memobj->whandle, 0, NULL, 0, NULL, NULL); if (pres) { if (pres->target != PIPE_BUFFER) zink_resource(pres)->valid = true; @@ -1714,7 +1747,7 @@ invalidate_buffer(struct zink_context *ctx, struct zink_resource *res) if (!zink_resource_has_usage(res)) return false; - struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, NULL, NULL, 0, NULL); + struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, NULL, NULL, 0, NULL, 0); if (!new_obj) { debug_printf("new backing resource alloc failed!\n"); return false; @@ -2664,6 +2697,9 @@ zink_screen_resource_init(struct pipe_screen *pscreen) pscreen->resource_get_handle = zink_resource_get_handle; pscreen->resource_from_handle = zink_resource_from_handle; } + if (screen->info.have_EXT_external_memory_host) { + pscreen->resource_from_user_memory = zink_resource_from_user_memory; + } if (screen->instance_info.have_KHR_external_memory_capabilities) { pscreen->memobj_create_from_handle = zink_memobj_create_from_handle; pscreen->memobj_destroy = zink_memobj_destroy; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 27b7c253fcd..96250178bc9 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -551,6 +551,8 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return screen->info.have_KHR_external_semaphore_fd || screen->info.have_KHR_external_semaphore_win32; case PIPE_CAP_NATIVE_FENCE_FD: return screen->instance_info.have_KHR_external_semaphore_capabilities && screen->info.have_KHR_external_semaphore_fd; + case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: + return screen->info.have_EXT_external_memory_host; case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: return screen->info.have_vulkan11 || screen->info.have_KHR_maintenance2;