[Mesa-dev] [RFC 5/6] anv/android: support creating images from external format
Tapani Pälli
tapani.palli at intel.com
Tue May 29 07:08:31 UTC 2018
Since we don't know the exact format at creation time, some initialization
is done only when bound with memory in vkBindImageMemory.
Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
---
src/intel/vulkan/anv_android.c | 40 ++++++++++++++
src/intel/vulkan/anv_image.c | 115 +++++++++++++++++++++++++++++++++++++++++
src/intel/vulkan/anv_private.h | 10 ++++
3 files changed, 165 insertions(+)
diff --git a/src/intel/vulkan/anv_android.c b/src/intel/vulkan/anv_android.c
index d1eb0b2e8b..c7e9d70e6d 100644
--- a/src/intel/vulkan/anv_android.c
+++ b/src/intel/vulkan/anv_android.c
@@ -284,6 +284,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_image.c b/src/intel/vulkan/anv_image.c
index 42496b6414..5aa67718da 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -595,6 +595,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);
@@ -630,6 +639,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);
@@ -684,6 +701,99 @@ static void anv_image_bind_memory_plane(struct anv_device *device,
image->planes[plane].bo_offset = memory_offset;
}
+#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,
@@ -694,6 +804,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 1fe3c38191..f04d78fba7 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2482,6 +2482,9 @@ struct anv_image {
*/
bool disjoint;
+ /* Image was created with external format. */
+ bool external_format;
+
/**
* Image subsurfaces
*
@@ -2861,6 +2864,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,
@@ -2875,6 +2879,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.3
More information about the mesa-dev
mailing list