Since we don't know the exact format at creation time, some initialization is done only when bound with memory in vkBindImageMemory.
v2: demand dedicated allocation in vkGetImageMemoryRequirements2 if image has external format Signed-off-by: Tapani Pälli <tapani.pa...@intel.com> --- src/intel/vulkan/anv_android.c | 40 ++++++++++++++ src/intel/vulkan/anv_device.c | 2 +- src/intel/vulkan/anv_image.c | 115 +++++++++++++++++++++++++++++++++++++++++ src/intel/vulkan/anv_private.h | 10 ++++ 4 files changed, 166 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_android.c b/src/intel/vulkan/anv_android.c index 6f90649847d..299b728a6f2 100644 --- a/src/intel/vulkan/anv_android.c +++ b/src/intel/vulkan/anv_android.c @@ -344,6 +344,46 @@ anv_create_ahw_memory(VkDevice device_h, return VK_SUCCESS; } +VkResult +anv_image_from_external( + VkDevice device_h, + const VkImageCreateInfo *base_info, + const struct VkExternalMemoryImageCreateInfo *create_info, + const VkAllocationCallbacks *alloc, + VkImage *out_image_h) +{ + ANV_FROM_HANDLE(anv_device, device, device_h); + VkImage image_h = VK_NULL_HANDLE; + struct anv_image *image = NULL; + VkResult result = VK_SUCCESS; + + /* Note, we can't set format, stride and such yet. */ + struct anv_image_create_info anv_info = { + .vk_info = base_info, + .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT, + .external_format = true, + }; + + const struct VkExternalFormatANDROID *ext_info = + vk_find_struct_const(base_info->pNext, EXTERNAL_FORMAT_ANDROID); + + if (ext_info && ext_info->externalFormat != 0) { + assert(base_info->format == VK_FORMAT_UNDEFINED); + assert(base_info->imageType == VK_IMAGE_TYPE_2D); + assert(base_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT); + assert(base_info->tiling == VK_IMAGE_TILING_OPTIMAL); + } + + result = anv_image_create(device_h, &anv_info, alloc, &image_h); + image = anv_image_from_handle(image_h); + if (result != VK_SUCCESS) + return result; + + *out_image_h = image_h; + + return result; +} + VkResult anv_image_from_gralloc(VkDevice device_h, const VkImageCreateInfo *base_info, diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 54919112d08..fbe057a8eec 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -2634,7 +2634,7 @@ void anv_GetImageMemoryRequirements2( switch (ext->sType) { case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { VkMemoryDedicatedRequirements *requirements = (void *)ext; - if (image->needs_set_tiling) { + if (image->needs_set_tiling || image->external_format) { /* If we need to set the tiling for external consumers, we need a * dedicated allocation. * diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index e4ab74a15d6..de03d64c6a7 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -596,6 +596,15 @@ anv_image_create(VkDevice _device, image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier : DRM_FORMAT_MOD_INVALID; + /* In case of external format, We don't know format yet, + * so skip the rest for now. + */ + if (create_info->external_format) { + image->external_format = true; + *pImage = anv_image_to_handle(image); + return VK_SUCCESS; + } + const struct anv_format *format = anv_get_format(image->vk_format); assert(format != NULL); @@ -631,6 +640,14 @@ anv_CreateImage(VkDevice device, VkImage *pImage) { #ifdef ANDROID + const struct VkExternalMemoryImageCreateInfo *create_info = + vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + + if (create_info && create_info->handleTypes & + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) + return anv_image_from_external(device, pCreateInfo, create_info, + pAllocator, pImage); + const VkNativeBufferANDROID *gralloc_info = vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID); @@ -687,6 +704,99 @@ static void anv_image_bind_memory_plane(struct anv_device *device, }; } +#ifdef ANDROID +/* We are binding AHardwareBuffer. Get a description and + * prepare anv_image properly. + */ +static void +prepare_ahw_image(struct anv_device *device, + struct anv_image *image, + struct anv_device_memory *mem) +{ + assert(mem->ahw); + + AHardwareBuffer_Desc desc; + AHardwareBuffer_describe(mem->ahw, &desc); + + /* Check tiling. */ + int i915_tiling = anv_gem_get_tiling(device, mem->bo->gem_handle); + VkImageTiling vk_tiling = 2; + + isl_tiling_flags_t isl_tiling_flags = 0; + + switch (i915_tiling) { + case I915_TILING_NONE: + vk_tiling = VK_IMAGE_TILING_LINEAR; + isl_tiling_flags = ISL_TILING_LINEAR_BIT; + break; + case I915_TILING_X: + vk_tiling = VK_IMAGE_TILING_OPTIMAL; + isl_tiling_flags = ISL_TILING_X_BIT; + break; + case I915_TILING_Y: + vk_tiling = VK_IMAGE_TILING_OPTIMAL; + isl_tiling_flags = ISL_TILING_Y0_BIT; + break; + case -1: + default: + unreachable("Invalid tiling flags."); + } + + assert(vk_tiling == VK_IMAGE_TILING_LINEAR || + vk_tiling == VK_IMAGE_TILING_OPTIMAL); + + /* Check format. */ + VkFormat vk_format = vk_format_from_android(desc.format); + enum isl_format isl_fmt = anv_get_isl_format(&device->info, + vk_format, + VK_IMAGE_ASPECT_COLOR_BIT, + vk_tiling); + assert(format != ISL_FORMAT_UNSUPPORTED); + + /* Now we should be able to fill anv_image fields properly and + * create isl_surface for it. + */ + image->vk_format = vk_format; + image->format = anv_get_format(vk_format); + image->aspects = vk_format_aspects(image->vk_format); + + const struct anv_format *format = anv_get_format(image->vk_format); + assert(format != NULL); + + image->n_planes = format->n_planes; + + /* Fill anv_image_create_info here so that we can call make_surface. */ + VkImageCreateInfo base_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = NULL, + .format = vk_format, + .imageType = VK_IMAGE_TYPE_2D, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .samples = image->samples, + .arrayLayers = image->array_size, + .mipLevels = image->levels, + .extent = image->extent, + }; + + struct anv_image_create_info anv_info = { + .vk_info = &base_info, + .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT, + .external_format = true, + }; + + anv_info.stride = desc.stride * + (isl_format_get_layout(isl_fmt)->bpb / 8); + + uint32_t b; + for_each_bit(b, image->aspects) { + VkResult r = make_surface(device, image, &anv_info, isl_tiling_flags, + (1 << b)); + assert(r == VK_SUCCESS); + } +} +#endif + VkResult anv_BindImageMemory( VkDevice _device, VkImage _image, @@ -697,6 +807,11 @@ VkResult anv_BindImageMemory( ANV_FROM_HANDLE(anv_device_memory, mem, _memory); ANV_FROM_HANDLE(anv_image, image, _image); +#ifdef ANDROID + if (mem->ahw && image->format == VK_FORMAT_UNDEFINED) + prepare_ahw_image(device, image, mem); +#endif + uint32_t aspect_bit; anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) { uint32_t plane = diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 56dee607dbe..7c01cf82a52 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2665,6 +2665,9 @@ struct anv_image { */ bool disjoint; + /* Image was created with external format. */ + bool external_format; + /** * Image subsurfaces * @@ -3040,6 +3043,7 @@ struct anv_image_create_info { isl_surf_usage_flags_t isl_extra_usage_flags; uint32_t stride; + bool external_format; }; VkResult anv_image_create(VkDevice _device, @@ -3054,6 +3058,12 @@ VkResult anv_image_from_gralloc(VkDevice device_h, const VkAllocationCallbacks *alloc, VkImage *pImage); +VkResult anv_image_from_external(VkDevice device_h, + const VkImageCreateInfo *base_info, + const struct VkExternalMemoryImageCreateInfo *create_info, + const VkAllocationCallbacks *alloc, + VkImage *out_image_h); + VkResult anv_import_ahw_memory(VkDevice device_h, struct anv_device_memory *mem, const VkImportAndroidHardwareBufferInfoANDROID *info); -- 2.14.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev