aux/vk: handle extFormatResolve in create_image

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2316>
This commit is contained in:
Simon Zeni 2024-08-28 11:50:09 -04:00
parent 8c272d1d96
commit 08f3965ad0
3 changed files with 76 additions and 39 deletions

View file

@ -804,28 +804,15 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla
XRT_CHECK_RESULT VkResult
vk_alloc_and_bind_image_memory(struct vk_bundle *vk,
VkImage image,
size_t max_size,
const VkMemoryRequirements *requirements,
const void *pNext_for_allocate,
const char *caller_name,
VkDeviceMemory *out_mem,
VkDeviceSize *out_size)
VkDeviceMemory *out_mem)
{
VkMemoryRequirements memory_requirements;
vk->vkGetImageMemoryRequirements(vk->device, image, &memory_requirements);
if (max_size > 0 && memory_requirements.size > max_size) {
VK_ERROR(vk, "(%s) vkGetImageMemoryRequirements: Requested more memory (%u) then given (%u)\n",
caller_name, (uint32_t)memory_requirements.size, (uint32_t)max_size);
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
if (out_size != NULL) {
*out_size = memory_requirements.size;
}
uint32_t memory_type_index = UINT32_MAX;
bool bret = vk_get_memory_type( //
vk, // vk_bundle
memory_requirements.memoryTypeBits, // type_bits
requirements->memoryTypeBits, // type_bits
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, // memory_props
&memory_type_index); // out_type_id
if (!bret) {
@ -836,7 +823,7 @@ vk_alloc_and_bind_image_memory(struct vk_bundle *vk,
VkMemoryAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = pNext_for_allocate,
.allocationSize = memory_requirements.size,
.allocationSize = requirements->size,
.memoryTypeIndex = memory_type_index,
};
@ -901,14 +888,16 @@ create_image_simple(struct vk_bundle *vk,
return ret;
}
VkMemoryRequirements requirements = {0};
vk->vkGetImageMemoryRequirements(vk->device, image, &requirements);
ret = vk_alloc_and_bind_image_memory( //
vk, // vk_bundle
image, // image
SIZE_MAX, // max_size
&requirements, // max_size
NULL, // pNext_for_allocate
__func__, // caller_name
out_mem, // out_mem
NULL); // out_size
out_mem); // out_mem
if (ret != VK_SUCCESS) {
// Clean up image
vk->vkDestroyImage(vk->device, image, NULL);
@ -1154,18 +1143,37 @@ vk_create_image_from_native(struct vk_bundle *vk,
// Nothing to cleanup
return ret;
}
VkMemoryRequirements requirements = {0};
vk->vkGetImageMemoryRequirements(vk->device, image, &requirements);
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
VkImportMemoryFdInfoKHR import_memory_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
.fd = image_native->handle,
};
// TODO memoryTypeBits from VkMemoryFdPropertiesKHR
#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
VkImportAndroidHardwareBufferInfoANDROID import_memory_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
.pNext = NULL,
.buffer = image_native->handle,
};
VkAndroidHardwareBufferPropertiesANDROID ahb_props = {
.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
};
ret = vk->vkGetAndroidHardwareBufferPropertiesANDROID(vk->device, image_native->handle, &ahb_props);
if (ret != VK_SUCCESS) {
VK_ERROR(vk, "vkGetAndroidHardwareBufferPropertiesANDROID: %s", vk_result_string(ret));
return ret;
}
requirements.size = ahb_props.allocationSize;
requirements.memoryTypeBits = ahb_props.memoryTypeBits;
#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE)
VkImportMemoryWin32HandleInfoKHR import_memory_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
@ -1173,9 +1181,20 @@ vk_create_image_from_native(struct vk_bundle *vk,
.handleType = handle_type,
.handle = image_native->handle,
};
// TODO memoryTypeBits from VkMemoryWin32HandlePropertiesKHR
#else
#error "need port"
#endif
if (requirements.size > image_native->size) {
VK_ERROR(vk, "size mismatch, exported %" PRIu64 " but requires %" PRIu64, image_native->size,
requirements.size);
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
} else if (requirements.size < image_native->size) {
VK_WARN(vk, "size mismatch, exported %" PRIu64 " but requires %" PRIu64, image_native->size,
requirements.size);
}
VkMemoryDedicatedAllocateInfoKHR dedicated_memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
.pNext = &import_memory_info,
@ -1186,11 +1205,10 @@ vk_create_image_from_native(struct vk_bundle *vk,
ret = vk_alloc_and_bind_image_memory( //
vk, // vk_bundle
image, // image
image_native->size, // max_size
&requirements, // requirements
&dedicated_memory_info, // pNext_for_allocate
__func__, // caller_name
out_mem, // out_mem
NULL); // out_size
out_mem); // out_mem
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_CONSUMED_BY_VULKAN_IMPORT)
// We have consumed this fd now, make sure it's not freed again.

View file

@ -1082,9 +1082,7 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla
*
* @param vk Vulkan bundle
* @param image The VkImage to allocate for and bind.
* @param max_size The maximum value you'll allow for
* VkMemoryRequirements::size. Pass SIZE_MAX if you will accept any size
* that works.
* @param requirements Memory requirements used for finding the memory type and the size.
* @param pNext_for_allocate (Optional) a pointer to use in the pNext chain of
* VkMemoryAllocateInfo.
* @param caller_name Used for error printing, this function is called from
@ -1104,11 +1102,10 @@ vk_get_memory_type(struct vk_bundle *vk, uint32_t type_bits, VkMemoryPropertyFla
XRT_CHECK_RESULT VkResult
vk_alloc_and_bind_image_memory(struct vk_bundle *vk,
VkImage image,
size_t max_size,
const VkMemoryRequirements *requirements,
const void *pNext_for_allocate,
const char *caller_name,
VkDeviceMemory *out_mem,
VkDeviceSize *out_size);
VkDeviceMemory *out_mem);
/*!
*
@ -1564,9 +1561,7 @@ vk_csci_get_image_external_support(struct vk_bundle *vk,
* CSCI = Compositor SwapChain Images.
*/
bool
vk_csci_is_format_supported(struct vk_bundle *vk,
VkFormat format,
enum xrt_swapchain_usage_bits xbits);
vk_csci_is_format_supported(struct vk_bundle *vk, VkFormat format, enum xrt_swapchain_usage_bits xbits);
/*
*

View file

@ -108,7 +108,6 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
VkDeviceMemory device_memory = VK_NULL_HANDLE;
VkImage image = VK_NULL_HANDLE;
VkResult ret = VK_SUCCESS;
VkDeviceSize size;
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
/*
@ -187,9 +186,8 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
};
CHAIN(format_android);
// Android can't allocate native sRGB.
// Use UNORM and correct gamma later.
if (image_format == VK_FORMAT_R8G8B8A8_SRGB) {
// Some versions of Android can't allocate native sRGB, use UNORM and correct gamma later.
image_format = VK_FORMAT_R8G8B8A8_UNORM;
// https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkImageViewCreateInfo-image-01019
@ -203,6 +201,20 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
add_format_non_dup(&flh, VK_FORMAT_R8G8B8A8_UNORM);
add_format_non_dup(&flh, VK_FORMAT_R8G8B8A8_SRGB);
}
if (vk_csci_is_format_supported(vk, image_format, info->bits)) {
// Format is supported, no need for VkExternalFormatANDROID
format_android.externalFormat = 0;
assert(a_buffer_format_props.format != VK_FORMAT_UNDEFINED); // Make sure there is a Vulkan format.
} else if (image_usage != VK_IMAGE_USAGE_SAMPLED_BIT && !vk->has_ANDROID_external_format_resolve) {
// VUID-VkImageCreateInfo-pNext-09457
VK_ERROR(
vk, "VK_ANDROID_external_format_resolve not supported, only VK_IMAGE_USAGE_SAMPLED_BIT is allowed");
return VK_ERROR_FORMAT_NOT_SUPPORTED;
} else {
VK_ERROR(vk, "Format not supported");
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
#endif
#ifdef VK_KHR_image_format_list
@ -270,7 +282,20 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
.pNext = &memory_dedicated_requirements,
};
VkMemoryRequirements *requirements;
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
// VUID-VkImageMemoryRequirementsInfo2-image-01897
// VUID-VkMemoryAllocateInfo-pNext-01874
// Use the requirements from the VkAndroidHardwareBufferPropertiesANDROID instead of querying them
VkMemoryRequirements android_memory_requirements = {
.size = a_buffer_props.allocationSize,
.memoryTypeBits = a_buffer_props.memoryTypeBits,
};
requirements = &android_memory_requirements;
#else
vk->vkGetImageMemoryRequirements2(vk->device, &memory_requirements_info, &memory_requirements);
requirements = &memory_requirements.memoryRequirements;
#endif
/*
* On tegra we must not use dedicated allocation when it is only preferred to avoid black textures and driver
@ -312,11 +337,10 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
ret = vk_alloc_and_bind_image_memory( //
vk, // vk_bundle
image, // image
SIZE_MAX, // max_size
requirements, // requirements
&export_alloc_info, // pNext_for_allocate
"vk_image_allocator::create_image", // caller_name
&device_memory, // out_mem
&size); // out_size
&device_memory); // out_mem
if (ret != VK_SUCCESS) {
vk->vkDestroyImage(vk->device, image, NULL);
return ret;
@ -324,7 +348,7 @@ create_image(struct vk_bundle *vk, const struct xrt_swapchain_create_info *info,
out_image->handle = image;
out_image->memory = device_memory;
out_image->size = size;
out_image->size = memory_requirements.memoryRequirements.size;
out_image->use_dedicated_allocation = use_dedicated_allocation;
return ret;