diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c index 0067b8c3f87..db1fc36e74a 100644 --- a/src/virtio/vulkan/vn_android.c +++ b/src/virtio/vulkan/vn_android.c @@ -516,6 +516,8 @@ vn_android_image_from_anb(struct vn_device *dev, goto fail; img->wsi.is_wsi = true; + img->wsi.tiling_override = builder.create.tiling; + img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier; /* Android WSI image owns the memory */ img->wsi.memory = vn_device_memory_from_handle(memory); img->wsi.memory_owned = true; diff --git a/src/virtio/vulkan/vn_image.c b/src/virtio/vulkan/vn_image.c index 206b458e8e0..99cb5e317a5 100644 --- a/src/virtio/vulkan/vn_image.c +++ b/src/virtio/vulkan/vn_image.c @@ -264,6 +264,16 @@ vn_CreateImage(VkDevice device, external_info->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; +#ifdef ANDROID + /* VkImageSwapchainCreateInfoKHR is not useful at all */ + const VkImageSwapchainCreateInfoKHR *swapchain_info = NULL; +#else + const VkImageSwapchainCreateInfoKHR *swapchain_info = vk_find_struct_const( + pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR); + if (swapchain_info && !swapchain_info->swapchain) + swapchain_info = NULL; +#endif + if (wsi_info) { result = vn_wsi_create_image(dev, pCreateInfo, wsi_info, alloc, &img); } else if (anb_info) { @@ -271,6 +281,9 @@ vn_CreateImage(VkDevice device, vn_android_image_from_anb(dev, pCreateInfo, anb_info, alloc, &img); } else if (ahb_info) { result = vn_android_image_from_ahb(dev, pCreateInfo, alloc, &img); + } else if (swapchain_info) { + result = vn_wsi_create_image_from_swapchain( + dev, pCreateInfo, swapchain_info, alloc, &img); } else { result = vn_image_create(dev, pCreateInfo, alloc, &img); } @@ -444,13 +457,35 @@ vn_BindImageMemory2(VkDevice device, struct vn_device_memory *mem = vn_device_memory_from_handle(info->memory); + /* no bind info fixup needed */ + if (mem && !mem->base_memory) { + if (img->wsi.is_wsi) + vn_image_bind_wsi_memory(img, mem); + continue; + } + + if (!mem) { +#ifdef ANDROID + /* TODO handle VkNativeBufferANDROID when we bump up + * VN_ANDROID_NATIVE_BUFFER_SPEC_VERSION + */ + unreachable("VkBindImageMemoryInfo with no memory"); +#else + const VkBindImageMemorySwapchainInfoKHR *swapchain_info = + vk_find_struct_const(info->pNext, + BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR); + assert(img->wsi.is_wsi && swapchain_info); + + struct vn_image *swapchain_img = + vn_image_from_handle(wsi_common_get_image( + swapchain_info->swapchain, swapchain_info->imageIndex)); + mem = swapchain_img->wsi.memory; +#endif + } + if (img->wsi.is_wsi) vn_image_bind_wsi_memory(img, mem); - /* TODO handle VkBindImageMemorySwapchainInfoKHR */ - if (!mem || !mem->base_memory) - continue; - if (!local_infos) { const size_t size = sizeof(*local_infos) * bindInfoCount; local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN, @@ -461,7 +496,12 @@ vn_BindImageMemory2(VkDevice device, memcpy(local_infos, pBindInfos, size); } - local_infos[i].memory = vn_device_memory_to_handle(mem->base_memory); + /* If mem is suballocated, mem->base_memory is non-NULL and we must + * patch it in. If VkBindImageMemorySwapchainInfoKHR is given, we've + * looked mem up above and also need to patch it in. + */ + local_infos[i].memory = vn_device_memory_to_handle( + mem->base_memory ? mem->base_memory : mem); local_infos[i].memoryOffset += mem->base_offset; } if (local_infos) diff --git a/src/virtio/vulkan/vn_image.h b/src/virtio/vulkan/vn_image.h index 02a3a4f76fa..c68114996bd 100644 --- a/src/virtio/vulkan/vn_image.h +++ b/src/virtio/vulkan/vn_image.h @@ -44,10 +44,14 @@ struct vn_image { struct { /* True if this is a swapchain image and VK_IMAGE_LAYOUT_PRESENT_SRC_KHR * is a valid layout. A swapchain image can be created internally - * (wsi_image_create_info) or externally (VkNativeBufferANDROID). + * (wsi_image_create_info) or externally (VkNativeBufferANDROID and + * VkImageSwapchainCreateInfoKHR). */ bool is_wsi; bool is_prime_blit_src; + VkImageTiling tiling_override; + /* valid when tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT */ + uint64_t drm_format_modifier; struct vn_device_memory *memory; diff --git a/src/virtio/vulkan/vn_wsi.c b/src/virtio/vulkan/vn_wsi.c index 795b6a9fb16..7419b587ea8 100644 --- a/src/virtio/vulkan/vn_wsi.c +++ b/src/virtio/vulkan/vn_wsi.c @@ -134,6 +134,81 @@ vn_wsi_create_image(struct vn_device *dev, img->wsi.is_wsi = true; img->wsi.is_prime_blit_src = wsi_info->prime_blit_src; + img->wsi.tiling_override = create_info->tiling; + + if (create_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { + VkDevice dev_handle = vn_device_to_handle(dev); + VkImage img_handle = vn_image_to_handle(img); + + VkImageDrmFormatModifierPropertiesEXT props = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, + }; + result = vn_GetImageDrmFormatModifierPropertiesEXT(dev_handle, + img_handle, &props); + if (result != VK_SUCCESS) { + vn_DestroyImage(dev_handle, img_handle, alloc); + return result; + } + + img->wsi.drm_format_modifier = props.drmFormatModifier; + } + + *out_img = img; + return VK_SUCCESS; +} + +VkResult +vn_wsi_create_image_from_swapchain( + struct vn_device *dev, + const VkImageCreateInfo *create_info, + const VkImageSwapchainCreateInfoKHR *swapchain_info, + const VkAllocationCallbacks *alloc, + struct vn_image **out_img) +{ + const struct vn_image *swapchain_img = vn_image_from_handle( + wsi_common_get_image(swapchain_info->swapchain, 0)); + assert(swapchain_img->wsi.is_wsi); + + /* must match what the common WSI and vn_wsi_create_image do */ + VkImageCreateInfo local_create_info = *create_info; + + /* match external memory */ + const VkExternalMemoryImageCreateInfo local_external_info = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .pNext = local_create_info.pNext, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + local_create_info.pNext = &local_external_info; + + /* match image tiling */ + local_create_info.tiling = swapchain_img->wsi.tiling_override; + + VkImageDrmFormatModifierListCreateInfoEXT local_mod_info; + if (local_create_info.tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) { + local_mod_info = (const VkImageDrmFormatModifierListCreateInfoEXT){ + .sType = + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, + .pNext = local_create_info.pNext, + .drmFormatModifierCount = 1, + .pDrmFormatModifiers = &swapchain_img->wsi.drm_format_modifier, + }; + local_create_info.pNext = &local_mod_info; + } + + /* match image usage */ + if (swapchain_img->wsi.is_prime_blit_src) + local_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + + create_info = &local_create_info; + + struct vn_image *img; + VkResult result = vn_image_create(dev, create_info, alloc, &img); + if (result != VK_SUCCESS) + return result; + + img->wsi.is_wsi = true; + img->wsi.tiling_override = swapchain_img->wsi.tiling_override; + img->wsi.drm_format_modifier = swapchain_img->wsi.drm_format_modifier; *out_img = img; return VK_SUCCESS; diff --git a/src/virtio/vulkan/vn_wsi.h b/src/virtio/vulkan/vn_wsi.h index e863f210c95..9d78fa7e552 100644 --- a/src/virtio/vulkan/vn_wsi.h +++ b/src/virtio/vulkan/vn_wsi.h @@ -37,6 +37,14 @@ vn_wsi_create_image(struct vn_device *dev, const VkAllocationCallbacks *alloc, struct vn_image **out_img); +VkResult +vn_wsi_create_image_from_swapchain( + struct vn_device *dev, + const VkImageCreateInfo *create_info, + const VkImageSwapchainCreateInfoKHR *swapchain_info, + const VkAllocationCallbacks *alloc, + struct vn_image **out_img); + #else static inline VkResult @@ -66,6 +74,17 @@ vn_wsi_create_image(struct vn_device *dev, return VK_ERROR_OUT_OF_HOST_MEMORY; } +static inline VkResult +vn_wsi_create_image_from_swapchain( + struct vn_device *dev, + const VkImageCreateInfo *create_info, + const VkImageSwapchainCreateInfoKHR *swapchain_info, + const VkAllocationCallbacks *alloc, + struct vn_image **out_img) +{ + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + #endif /* VN_USE_WSI_PLATFORM */ #endif /* VN_WSI_H */