v3dv: implement interactions of VK_KHR_device_group with VK_KHR_swapchain

There are some interactions between these two extensions that need to be
implemented when both are supported. Particularly:

1. Applications can create images that will be bound to swapchain memory
   by passing a VkImageSwapchainCreateInfoKHR in the pNext chain
   of VkImageCreateInfo. In this case we need to make sure that the
   created image takes some of its parameters from the underlying
   swapchain.

2. Applications can bind memory from a swapchain image to a VkImage
   by passing a VkBindImageMemorySwapchainInfoKHR in the pNext chain
   of VkBindImageMemoryInfo.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11037>
This commit is contained in:
Iago Toral Quiroga 2021-05-27 10:17:08 +02:00 committed by Marge Bot
parent bf60ba6e7f
commit c672b23857
4 changed files with 93 additions and 2 deletions

View file

@ -2030,8 +2030,25 @@ v3dv_BindImageMemory2(VkDevice _device,
uint32_t bindInfoCount,
const VkBindImageMemoryInfo *pBindInfos)
{
for (uint32_t i = 0; i < bindInfoCount; i++)
bind_image_memory(&pBindInfos[i]);
for (uint32_t i = 0; i < bindInfoCount; i++) {
const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
vk_find_struct_const(pBindInfos->pNext,
BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
if (swapchain_info && swapchain_info->swapchain) {
struct v3dv_image *swapchain_image =
v3dv_wsi_get_image_from_swapchain(swapchain_info->swapchain,
swapchain_info->imageIndex);
VkBindImageMemoryInfo swapchain_bind = {
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
.image = pBindInfos[i].image,
.memory = v3dv_device_memory_to_handle(swapchain_image->mem),
.memoryOffset = swapchain_image->mem_offset,
};
bind_image_memory(&swapchain_bind);
} else {
bind_image_memory(&pBindInfos[i]);
}
}
return VK_SUCCESS;
}

View file

@ -345,6 +345,53 @@ create_image(struct v3dv_device *device,
return VK_SUCCESS;
}
static VkResult
create_image_from_swapchain(struct v3dv_device *device,
const VkImageCreateInfo *pCreateInfo,
const VkImageSwapchainCreateInfoKHR *swapchain_info,
const VkAllocationCallbacks *pAllocator,
VkImage *pImage)
{
struct v3dv_image *swapchain_image =
v3dv_wsi_get_image_from_swapchain(swapchain_info->swapchain, 0);
assert(swapchain_image);
VkImageCreateInfo local_create_info = *pCreateInfo;
local_create_info.pNext = NULL;
/* Added by wsi code. */
local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
/* The spec requires TILING_OPTIMAL as input, but the swapchain image may
* privately use a different tiling. See spec anchor
* #swapchain-wsi-image-create-info .
*/
assert(local_create_info.tiling == VK_IMAGE_TILING_OPTIMAL);
local_create_info.tiling = swapchain_image->tiling;
VkImageDrmFormatModifierListCreateInfoEXT local_modifier_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
.drmFormatModifierCount = 1,
.pDrmFormatModifiers = &swapchain_image->drm_format_mod,
};
if (swapchain_image->drm_format_mod != DRM_FORMAT_MOD_INVALID)
__vk_append_struct(&local_create_info, &local_modifier_info);
assert(swapchain_image->type == local_create_info.imageType);
assert(swapchain_image->vk_format == local_create_info.format);
assert(swapchain_image->extent.width == local_create_info.extent.width);
assert(swapchain_image->extent.height == local_create_info.extent.height);
assert(swapchain_image->extent.depth == local_create_info.extent.depth);
assert(swapchain_image->array_size == local_create_info.arrayLayers);
assert(swapchain_image->samples == local_create_info.samples);
assert(swapchain_image->tiling == local_create_info.tiling);
assert((swapchain_image->usage & local_create_info.usage) ==
local_create_info.usage);
return create_image(device, &local_create_info, pAllocator, pImage);
}
VkResult
v3dv_CreateImage(VkDevice _device,
const VkImageCreateInfo *pCreateInfo,
@ -352,6 +399,13 @@ v3dv_CreateImage(VkDevice _device,
VkImage *pImage)
{
V3DV_FROM_HANDLE(v3dv_device, device, _device);
const VkImageSwapchainCreateInfoKHR *swapchain_info =
vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
return create_image_from_swapchain(device, pCreateInfo, swapchain_info,
pAllocator, pImage);
return create_image(device, pCreateInfo, pAllocator, pImage);
}

View file

@ -166,6 +166,8 @@ VkResult v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
VkResult v3dv_wsi_init(struct v3dv_physical_device *physical_device);
void v3dv_wsi_finish(struct v3dv_physical_device *physical_device);
struct v3dv_image *v3dv_wsi_get_image_from_swapchain(VkSwapchainKHR swapchain,
uint32_t index);
void v3dv_meta_clear_init(struct v3dv_device *device);
void v3dv_meta_clear_finish(struct v3dv_device *device);

View file

@ -262,6 +262,24 @@ VkResult v3dv_GetSwapchainImagesKHR(
pSwapchainImages);
}
struct v3dv_image *
v3dv_wsi_get_image_from_swapchain(VkSwapchainKHR swapchain, uint32_t index)
{
uint32_t n_images = index + 1;
VkImage *images = malloc(sizeof(*images) * n_images);
VkResult result = wsi_common_get_images(swapchain, &n_images, images);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
free(images);
return NULL;
}
V3DV_FROM_HANDLE(v3dv_image, image, images[index]);
free(images);
return image;
}
VkResult v3dv_AcquireNextImageKHR(
VkDevice device,
VkSwapchainKHR swapchain,