anv/android: support creating images from external format
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
v3: refactor prepare_ahw_image, support vkBindImageMemory2,
calculate stride correctly for rgb(x) surfaces, rename as
'resolve_ahw_image'
v4: rebase to b43f955037
changes
v5: add some assertions to verify input correctness (Lionel)
Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
This commit is contained in:
parent
517103abf1
commit
f1654fa7e3
|
@ -373,6 +373,42 @@ anv_create_ahw_memory(VkDevice device_h,
|
||||||
return VK_SUCCESS;
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct anv_image_create_info anv_info = {
|
||||||
|
.vk_info = base_info,
|
||||||
|
.isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT,
|
||||||
|
.external_format = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImage image_h;
|
||||||
|
VkResult result = anv_image_create(device_h, &anv_info, alloc, &image_h);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
*out_image_h = image_h;
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
anv_image_from_gralloc(VkDevice device_h,
|
anv_image_from_gralloc(VkDevice device_h,
|
||||||
const VkImageCreateInfo *base_info,
|
const VkImageCreateInfo *base_info,
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <vulkan/vk_android_native_buffer.h>
|
#include <vulkan/vk_android_native_buffer.h>
|
||||||
|
|
||||||
struct anv_device_memory;
|
struct anv_device_memory;
|
||||||
|
struct anv_device;
|
||||||
|
struct anv_image;
|
||||||
|
|
||||||
VkResult anv_image_from_gralloc(VkDevice device_h,
|
VkResult anv_image_from_gralloc(VkDevice device_h,
|
||||||
const VkImageCreateInfo *base_info,
|
const VkImageCreateInfo *base_info,
|
||||||
|
@ -36,6 +38,12 @@ VkResult anv_image_from_gralloc(VkDevice device_h,
|
||||||
const VkAllocationCallbacks *alloc,
|
const VkAllocationCallbacks *alloc,
|
||||||
VkImage *pImage);
|
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);
|
||||||
|
|
||||||
uint64_t anv_ahw_usage_from_vk_usage(const VkImageCreateFlags vk_create,
|
uint64_t anv_ahw_usage_from_vk_usage(const VkImageCreateFlags vk_create,
|
||||||
const VkImageUsageFlags vk_usage);
|
const VkImageUsageFlags vk_usage);
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,13 @@ anv_create_ahw_memory(VkDevice device_h,
|
||||||
{
|
{
|
||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkResult
|
||||||
|
anv_image_from_external(VkDevice device_h,
|
||||||
|
const VkImageCreateInfo *base_info,
|
||||||
|
const struct VkExternalMemoryImageCreateInfo *create_info,
|
||||||
|
const VkAllocationCallbacks *alloc,
|
||||||
|
VkImage *out_image_h)
|
||||||
|
{
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
|
@ -2712,6 +2712,12 @@ void anv_GetImageMemoryRequirements(
|
||||||
*/
|
*/
|
||||||
uint32_t memory_types = (1ull << pdevice->memory.type_count) - 1;
|
uint32_t memory_types = (1ull << pdevice->memory.type_count) - 1;
|
||||||
|
|
||||||
|
/* We must have image allocated or imported at this point. According to the
|
||||||
|
* specification, external images must have been bound to memory before
|
||||||
|
* calling GetImageMemoryRequirements.
|
||||||
|
*/
|
||||||
|
assert(image->size > 0);
|
||||||
|
|
||||||
pMemoryRequirements->size = image->size;
|
pMemoryRequirements->size = image->size;
|
||||||
pMemoryRequirements->alignment = image->alignment;
|
pMemoryRequirements->alignment = image->alignment;
|
||||||
pMemoryRequirements->memoryTypeBits = memory_types;
|
pMemoryRequirements->memoryTypeBits = memory_types;
|
||||||
|
@ -2752,6 +2758,12 @@ void anv_GetImageMemoryRequirements2(
|
||||||
pMemoryRequirements->memoryRequirements.memoryTypeBits =
|
pMemoryRequirements->memoryRequirements.memoryTypeBits =
|
||||||
(1ull << pdevice->memory.type_count) - 1;
|
(1ull << pdevice->memory.type_count) - 1;
|
||||||
|
|
||||||
|
/* We must have image allocated or imported at this point. According to the
|
||||||
|
* specification, external images must have been bound to memory before
|
||||||
|
* calling GetImageMemoryRequirements.
|
||||||
|
*/
|
||||||
|
assert(image->planes[plane].size > 0);
|
||||||
|
|
||||||
pMemoryRequirements->memoryRequirements.size = image->planes[plane].size;
|
pMemoryRequirements->memoryRequirements.size = image->planes[plane].size;
|
||||||
pMemoryRequirements->memoryRequirements.alignment =
|
pMemoryRequirements->memoryRequirements.alignment =
|
||||||
image->planes[plane].alignment;
|
image->planes[plane].alignment;
|
||||||
|
@ -2768,7 +2780,7 @@ void anv_GetImageMemoryRequirements2(
|
||||||
switch (ext->sType) {
|
switch (ext->sType) {
|
||||||
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
|
||||||
VkMemoryDedicatedRequirements *requirements = (void *)ext;
|
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
|
/* If we need to set the tiling for external consumers, we need a
|
||||||
* dedicated allocation.
|
* dedicated allocation.
|
||||||
*
|
*
|
||||||
|
|
|
@ -594,6 +594,15 @@ anv_image_create(VkDevice _device,
|
||||||
image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier :
|
image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier :
|
||||||
DRM_FORMAT_MOD_INVALID;
|
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);
|
const struct anv_format *format = anv_get_format(image->vk_format);
|
||||||
assert(format != NULL);
|
assert(format != NULL);
|
||||||
|
|
||||||
|
@ -635,9 +644,16 @@ anv_CreateImage(VkDevice device,
|
||||||
const VkAllocationCallbacks *pAllocator,
|
const VkAllocationCallbacks *pAllocator,
|
||||||
VkImage *pImage)
|
VkImage *pImage)
|
||||||
{
|
{
|
||||||
|
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 =
|
const VkNativeBufferANDROID *gralloc_info =
|
||||||
vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
|
vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
|
||||||
|
|
||||||
if (gralloc_info)
|
if (gralloc_info)
|
||||||
return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,
|
return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,
|
||||||
pAllocator, pImage);
|
pAllocator, pImage);
|
||||||
|
@ -690,6 +706,83 @@ static void anv_image_bind_memory_plane(struct anv_device *device,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are binding AHardwareBuffer. Get a description, resolve the
|
||||||
|
* format and prepare anv_image properly.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
resolve_ahw_image(struct anv_device *device,
|
||||||
|
struct anv_image *image,
|
||||||
|
struct anv_device_memory *mem)
|
||||||
|
{
|
||||||
|
#ifdef ANDROID
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Handle RGB(X)->RGBA fallback. */
|
||||||
|
switch (desc.format) {
|
||||||
|
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
||||||
|
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
||||||
|
if (isl_format_is_rgb(isl_fmt))
|
||||||
|
isl_fmt = isl_format_rgb_to_rgba(isl_fmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we are 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);
|
||||||
|
image->n_planes = image->format->n_planes;
|
||||||
|
image->ccs_e_compatible = false;
|
||||||
|
|
||||||
|
uint32_t 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, stride, isl_tiling_flags,
|
||||||
|
ISL_SURF_USAGE_DISABLE_AUX_BIT, (1 << b));
|
||||||
|
assert(r == VK_SUCCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
VkResult anv_BindImageMemory(
|
VkResult anv_BindImageMemory(
|
||||||
VkDevice _device,
|
VkDevice _device,
|
||||||
VkImage _image,
|
VkImage _image,
|
||||||
|
@ -700,6 +793,9 @@ VkResult anv_BindImageMemory(
|
||||||
ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
|
ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
|
||||||
ANV_FROM_HANDLE(anv_image, image, _image);
|
ANV_FROM_HANDLE(anv_image, image, _image);
|
||||||
|
|
||||||
|
if (mem->ahw)
|
||||||
|
resolve_ahw_image(device, image, mem);
|
||||||
|
|
||||||
uint32_t aspect_bit;
|
uint32_t aspect_bit;
|
||||||
anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) {
|
anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) {
|
||||||
uint32_t plane =
|
uint32_t plane =
|
||||||
|
@ -721,8 +817,11 @@ VkResult anv_BindImageMemory2(
|
||||||
const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
|
const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
|
||||||
ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
|
ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
|
||||||
ANV_FROM_HANDLE(anv_image, image, bind_info->image);
|
ANV_FROM_HANDLE(anv_image, image, bind_info->image);
|
||||||
VkImageAspectFlags aspects = image->aspects;
|
|
||||||
|
|
||||||
|
if (mem->ahw)
|
||||||
|
resolve_ahw_image(device, image, mem);
|
||||||
|
|
||||||
|
VkImageAspectFlags aspects = image->aspects;
|
||||||
vk_foreach_struct_const(s, bind_info->pNext) {
|
vk_foreach_struct_const(s, bind_info->pNext) {
|
||||||
switch (s->sType) {
|
switch (s->sType) {
|
||||||
case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
|
case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
|
||||||
|
|
|
@ -2699,6 +2699,9 @@ struct anv_image {
|
||||||
*/
|
*/
|
||||||
bool ccs_e_compatible;
|
bool ccs_e_compatible;
|
||||||
|
|
||||||
|
/* Image was created with external format. */
|
||||||
|
bool external_format;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image subsurfaces
|
* Image subsurfaces
|
||||||
*
|
*
|
||||||
|
@ -3073,6 +3076,7 @@ struct anv_image_create_info {
|
||||||
isl_surf_usage_flags_t isl_extra_usage_flags;
|
isl_surf_usage_flags_t isl_extra_usage_flags;
|
||||||
|
|
||||||
uint32_t stride;
|
uint32_t stride;
|
||||||
|
bool external_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
VkResult anv_image_create(VkDevice _device,
|
VkResult anv_image_create(VkDevice _device,
|
||||||
|
|
Loading…
Reference in New Issue