diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index 75f37c2693d..2e447e1c6cb 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -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; } diff --git a/src/broadcom/vulkan/v3dv_image.c b/src/broadcom/vulkan/v3dv_image.c index 9400a85e0e4..4d56e82d54c 100644 --- a/src/broadcom/vulkan/v3dv_image.c +++ b/src/broadcom/vulkan/v3dv_image.c @@ -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); } diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 1adc51ed447..6548f45b7d0 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -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); diff --git a/src/broadcom/vulkan/v3dv_wsi.c b/src/broadcom/vulkan/v3dv_wsi.c index 97616985214..0094994d570 100644 --- a/src/broadcom/vulkan/v3dv_wsi.c +++ b/src/broadcom/vulkan/v3dv_wsi.c @@ -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,