From 5b13d74583513ddd029e30c989838b96993545a0 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 22 Jul 2021 17:50:38 -0500 Subject: [PATCH] vulkan/wsi/drm: Break create_native_image in pieces Instead of making create_native_image one monolithic function, break it into a configure stage and a create stage. The configure stage is further broken up, first into a common piece that constructs a simple VkImageCreateInfo and a couple chain-ins. The second adds the extra stuff for create_native_image. This is to prepare for eventually storing those structs in the swapchain itself. Acked-by: Erik Faye-Lund Part-of: --- src/vulkan/wsi/wsi_common.c | 103 +++++++++++ src/vulkan/wsi/wsi_common_drm.c | 255 +++++++++++++--------------- src/vulkan/wsi/wsi_common_private.h | 35 ++++ 3 files changed, 260 insertions(+), 133 deletions(-) diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index cbec43959af..d549dad8687 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -353,6 +353,109 @@ wsi_swapchain_finish(struct wsi_swapchain *chain) vk_object_base_finish(&chain->base); } +VkResult +wsi_configure_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + VkExternalMemoryHandleTypeFlags handle_types, + struct wsi_image_info *info) +{ + memset(info, 0, sizeof(*info)); + + uint32_t *queue_family_indices = + vk_alloc(&chain->alloc, + sizeof(*queue_family_indices) * + pCreateInfo->queueFamilyIndexCount, + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!queue_family_indices) + goto err_oom; + for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) + queue_family_indices[i] = pCreateInfo->pQueueFamilyIndices[i]; + + info->create = (VkImageCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .flags = 0, + .imageType = VK_IMAGE_TYPE_2D, + .format = pCreateInfo->imageFormat, + .extent = { + .width = pCreateInfo->imageExtent.width, + .height = pCreateInfo->imageExtent.height, + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = pCreateInfo->imageUsage, + .sharingMode = pCreateInfo->imageSharingMode, + .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, + .pQueueFamilyIndices = queue_family_indices, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; + + if (handle_types != 0) { + info->ext_mem = (VkExternalMemoryImageCreateInfo) { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .handleTypes = handle_types, + }; + __vk_append_struct(&info->create, &info->ext_mem); + } + + info->wsi = (struct wsi_image_create_info) { + .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, + .scanout = true, + }; + __vk_append_struct(&info->create, &info->wsi); + + if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) { + info->create.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR; + + const VkImageFormatListCreateInfoKHR *format_list_in = + vk_find_struct_const(pCreateInfo->pNext, + IMAGE_FORMAT_LIST_CREATE_INFO_KHR); + + assume(format_list_in && format_list_in->viewFormatCount > 0); + + const uint32_t view_format_count = format_list_in->viewFormatCount; + VkFormat *view_formats = + vk_alloc(&chain->alloc, sizeof(VkFormat) * view_format_count, + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!view_formats) + goto err_oom; + + ASSERTED bool format_found = false; + for (uint32_t i = 0; i < format_list_in->viewFormatCount; i++) { + if (pCreateInfo->imageFormat == format_list_in->pViewFormats[i]) + format_found = true; + view_formats[i] = format_list_in->pViewFormats[i]; + } + assert(format_found); + + info->format_list = (VkImageFormatListCreateInfoKHR) { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR, + .viewFormatCount = view_format_count, + .pViewFormats = view_formats, + }; + __vk_append_struct(&info->create, &info->format_list); + } + + return VK_SUCCESS; + +err_oom: + wsi_destroy_image_info(chain, info); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +void +wsi_destroy_image_info(const struct wsi_swapchain *chain, + struct wsi_image_info *info) +{ + vk_free(&chain->alloc, (void *)info->create.pQueueFamilyIndices); + vk_free(&chain->alloc, (void *)info->format_list.pViewFormats); + vk_free(&chain->alloc, (void *)info->drm_mod_list.pDrmFormatModifiers); + vk_free(&chain->alloc, info->modifier_props); +} + void wsi_destroy_image(const struct wsi_swapchain *chain, struct wsi_image *image) diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c index de0c85f6d8a..3a212e1cb35 100644 --- a/src/vulkan/wsi/wsi_common_drm.c +++ b/src/vulkan/wsi/wsi_common_drm.c @@ -126,84 +126,39 @@ vk_format_size(VkFormat format) } } +static const struct VkDrmFormatModifierPropertiesEXT * +get_modifier_props(const struct wsi_image_info *info, uint64_t modifier) +{ + for (uint32_t i = 0; i < info->modifier_prop_count; i++) { + if (info->modifier_props[i].drmFormatModifier == modifier) + return &info->modifier_props[i]; + } + return NULL; +} + VkResult -wsi_create_native_image(const struct wsi_swapchain *chain, - const VkSwapchainCreateInfoKHR *pCreateInfo, - uint32_t num_modifier_lists, - const uint32_t *num_modifiers, - const uint64_t *const *modifiers, - uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size), - struct wsi_image *image) +wsi_configure_native_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + uint32_t num_modifier_lists, + const uint32_t *num_modifiers, + const uint64_t *const *modifiers, + uint8_t *(alloc_shm)(struct wsi_image *image, + unsigned size), + struct wsi_image_info *info) { const struct wsi_device *wsi = chain->wsi; - VkResult result; - memset(image, 0, sizeof(*image)); - for (int i = 0; i < ARRAY_SIZE(image->fds); i++) - image->fds[i] = -1; + VkExternalMemoryHandleTypeFlags handle_type = + wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT : + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; - struct wsi_image_create_info image_wsi_info = { - .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, - }; - VkExternalMemoryImageCreateInfo ext_mem_image_create_info = { - .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, - .pNext = &image_wsi_info, - .handleTypes = wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT : - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, - }; - VkImageCreateInfo image_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = &ext_mem_image_create_info, - .flags = 0, - .imageType = VK_IMAGE_TYPE_2D, - .format = pCreateInfo->imageFormat, - .extent = { - .width = pCreateInfo->imageExtent.width, - .height = pCreateInfo->imageExtent.height, - .depth = 1, - }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = pCreateInfo->imageUsage, - .sharingMode = pCreateInfo->imageSharingMode, - .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, - .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - }; + VkResult result = wsi_configure_image(chain, pCreateInfo, handle_type, info); + if (result != VK_SUCCESS) + return result; - VkImageFormatListCreateInfoKHR image_format_list; - if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) { - image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | - VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR; - - const VkImageFormatListCreateInfoKHR *format_list = - vk_find_struct_const(pCreateInfo->pNext, - IMAGE_FORMAT_LIST_CREATE_INFO_KHR); - -#ifndef NDEBUG - assume(format_list && format_list->viewFormatCount > 0); - bool format_found = false; - for (int i = 0; i < format_list->viewFormatCount; i++) - if (pCreateInfo->imageFormat == format_list->pViewFormats[i]) - format_found = true; - assert(format_found); -#endif - - image_format_list = *format_list; - image_format_list.pNext = NULL; - __vk_append_struct(&image_info, &image_format_list); - } - - VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list; - - uint32_t image_modifier_count = 0, modifier_prop_count = 0; - struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL; - uint64_t *image_modifiers = NULL; if (num_modifier_lists == 0) { /* If we don't have modifiers, fall back to the legacy "scanout" flag */ - image_wsi_info.scanout = true; + info->wsi.scanout = true; } else { /* The winsys can't request modifiers if we don't support them. */ assert(wsi->supports_modifiers); @@ -218,17 +173,15 @@ wsi_create_native_image(const struct wsi_swapchain *chain, pCreateInfo->imageFormat, &format_props); assert(modifier_props_list.drmFormatModifierCount > 0); - modifier_props = vk_alloc(&chain->alloc, - sizeof(*modifier_props) * - modifier_props_list.drmFormatModifierCount, - 8, - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); - if (!modifier_props) { - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto fail; - } + info->modifier_props = + vk_alloc(&chain->alloc, + sizeof(*info->modifier_props) * + modifier_props_list.drmFormatModifierCount, + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (info->modifier_props == NULL) + goto fail_oom; - modifier_props_list.pDrmFormatModifierProperties = modifier_props; + modifier_props_list.pDrmFormatModifierProperties = info->modifier_props; wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, pCreateInfo->imageFormat, &format_props); @@ -236,11 +189,11 @@ wsi_create_native_image(const struct wsi_swapchain *chain, /* Call GetImageFormatProperties with every modifier and filter the list * down to those that we know work. */ - modifier_prop_count = 0; + info->modifier_prop_count = 0; for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) { VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, - .drmFormatModifier = modifier_props[i].drmFormatModifier, + .drmFormatModifier = info->modifier_props[i].drmFormatModifier, .sharingMode = pCreateInfo->imageSharingMode, .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, @@ -251,12 +204,12 @@ wsi_create_native_image(const struct wsi_swapchain *chain, .type = VK_IMAGE_TYPE_2D, .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, .usage = pCreateInfo->imageUsage, - .flags = image_info.flags, + .flags = info->create.flags, }; VkImageFormatListCreateInfoKHR format_list; - if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { - format_list = image_format_list; + if (info->create.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { + format_list = info->format_list; format_list.pNext = NULL; __vk_append_struct(&format_info, &format_list); } @@ -270,33 +223,27 @@ wsi_create_native_image(const struct wsi_swapchain *chain, &format_info, &format_props); if (result == VK_SUCCESS) - modifier_props[modifier_prop_count++] = modifier_props[i]; + info->modifier_props[info->modifier_prop_count++] = info->modifier_props[i]; } uint32_t max_modifier_count = 0; for (uint32_t l = 0; l < num_modifier_lists; l++) max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]); - image_modifiers = vk_alloc(&chain->alloc, - sizeof(*image_modifiers) * - max_modifier_count, - 8, - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); - if (!image_modifiers) { - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto fail; - } + uint64_t *image_modifiers = + vk_alloc(&chain->alloc, sizeof(*image_modifiers) * max_modifier_count, + 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!image_modifiers) + goto fail_oom; - image_modifier_count = 0; + uint32_t image_modifier_count = 0; for (uint32_t l = 0; l < num_modifier_lists; l++) { /* Walk the modifier lists and construct a list of supported * modifiers. */ for (uint32_t i = 0; i < num_modifiers[l]; i++) { - for (uint32_t j = 0; j < modifier_prop_count; j++) { - if (modifier_props[j].drmFormatModifier == modifiers[l][i]) - image_modifiers[image_modifier_count++] = modifiers[l][i]; - } + if (get_modifier_props(info, modifiers[l][i])) + image_modifiers[image_modifier_count++] = modifiers[l][i]; } /* We only want to take the modifiers from the first list */ @@ -305,32 +252,45 @@ wsi_create_native_image(const struct wsi_swapchain *chain, } if (image_modifier_count > 0) { - image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) { + info->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + info->drm_mod_list = (VkImageDrmFormatModifierListCreateInfoEXT) { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, .drmFormatModifierCount = image_modifier_count, .pDrmFormatModifiers = image_modifiers, }; - image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - __vk_append_struct(&image_info, &image_modifier_list); + image_modifiers = NULL; + __vk_append_struct(&info->create, &info->drm_mod_list); } else { + vk_free(&chain->alloc, image_modifiers); /* TODO: Add a proper error here */ assert(!"Failed to find a supported modifier! This should never " "happen because LINEAR should always be available"); - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto fail; + goto fail_oom; } } - result = wsi->CreateImage(chain->device, &image_info, - &chain->alloc, &image->image); - if (result != VK_SUCCESS) - goto fail; + info->alloc_shm = alloc_shm; + + return VK_SUCCESS; + +fail_oom: + wsi_destroy_image_info(chain, info); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult +wsi_create_native_image_mem(const struct wsi_swapchain *chain, + const struct wsi_image_info *info, + struct wsi_image *image) +{ + const struct wsi_device *wsi = chain->wsi; + VkResult result; VkMemoryRequirements reqs; wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); void *sw_host_ptr = NULL; - if (alloc_shm) { + if (info->alloc_shm) { VkSubresourceLayout layout; wsi->GetImageSubresourceLayout(chain->device, image->image, @@ -339,7 +299,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain, .mipLevel = 0, .arrayLayer = 0, }, &layout); - sw_host_ptr = (*alloc_shm)(image, layout.size); + sw_host_ptr = info->alloc_shm(image, layout.size); } const struct wsi_memory_allocate_info memory_wsi_info = { @@ -374,12 +334,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain, result = wsi->AllocateMemory(chain->device, &memory_info, &chain->alloc, &image->memory); if (result != VK_SUCCESS) - goto fail; - - result = wsi->BindImageMemory(chain->device, image->image, - image->memory, 0); - if (result != VK_SUCCESS) - goto fail; + return result; int fd = -1; if (!wsi->sw) { @@ -392,10 +347,10 @@ wsi_create_native_image(const struct wsi_swapchain *chain, result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd); if (result != VK_SUCCESS) - goto fail; + return result; } - if (!wsi->sw && num_modifier_lists > 0) { + if (!wsi->sw && info->drm_mod_list.drmFormatModifierCount > 0) { VkImageDrmFormatModifierPropertiesEXT image_mod_props = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, }; @@ -404,17 +359,14 @@ wsi_create_native_image(const struct wsi_swapchain *chain, &image_mod_props); if (result != VK_SUCCESS) { close(fd); - goto fail; + return result; } image->drm_modifier = image_mod_props.drmFormatModifier; assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID); - for (uint32_t j = 0; j < modifier_prop_count; j++) { - if (modifier_props[j].drmFormatModifier == image->drm_modifier) { - image->num_planes = modifier_props[j].drmFormatModifierPlaneCount; - break; - } - } + const struct VkDrmFormatModifierPropertiesEXT *mod_props = + get_modifier_props(info, image->drm_modifier); + image->num_planes = mod_props->drmFormatModifierPlaneCount; for (uint32_t p = 0; p < image->num_planes; p++) { const VkImageSubresource image_subresource = { @@ -436,8 +388,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain, for (uint32_t i = 0; i < p; i++) close(image->fds[i]); - result = VK_ERROR_OUT_OF_HOST_MEMORY; - goto fail; + return VK_ERROR_OUT_OF_HOST_MEMORY; } } } @@ -459,16 +410,54 @@ wsi_create_native_image(const struct wsi_swapchain *chain, image->fds[0] = fd; } - vk_free(&chain->alloc, modifier_props); - vk_free(&chain->alloc, image_modifiers); + return VK_SUCCESS; +} + +VkResult +wsi_create_native_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + uint32_t num_modifier_lists, + const uint32_t *num_modifiers, + const uint64_t *const *modifiers, + uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size), + struct wsi_image *image) +{ + const struct wsi_device *wsi = chain->wsi; + VkResult result; + + memset(image, 0, sizeof(*image)); + for (int i = 0; i < ARRAY_SIZE(image->fds); i++) + image->fds[i] = -1; + + struct wsi_image_info info; + result = wsi_configure_native_image(chain, pCreateInfo, + num_modifier_lists, + num_modifiers, modifiers, + alloc_shm, &info); + if (result != VK_SUCCESS) + return result; + + result = wsi->CreateImage(chain->device, &info.create, + &chain->alloc, &image->image); + if (result != VK_SUCCESS) + goto fail; + + result = wsi_create_native_image_mem(chain, &info, image); + if (result != VK_SUCCESS) + goto fail; + + result = wsi->BindImageMemory(chain->device, image->image, + image->memory, 0); + if (result != VK_SUCCESS) + goto fail; + + wsi_destroy_image_info(chain, &info); return VK_SUCCESS; fail: - vk_free(&chain->alloc, modifier_props); - vk_free(&chain->alloc, image_modifiers); + wsi_destroy_image_info(chain, &info); wsi_destroy_image(chain, image); - return result; } diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h index 3d4961d0b35..0e8c1511153 100644 --- a/src/vulkan/wsi/wsi_common_private.h +++ b/src/vulkan/wsi/wsi_common_private.h @@ -26,6 +26,24 @@ #include "wsi_common.h" #include "vulkan/runtime/vk_object.h" +struct wsi_image; + +struct wsi_image_info { + VkImageCreateInfo create; + struct wsi_image_create_info wsi; + VkExternalMemoryImageCreateInfo ext_mem; + VkImageFormatListCreateInfoKHR format_list; + VkImageDrmFormatModifierListCreateInfoEXT drm_mod_list; + + /* Not really part of VkImageCreateInfo but needed to figure out the + * number of planes we need to bind. + */ + uint32_t modifier_prop_count; + struct VkDrmFormatModifierPropertiesEXT *modifier_props; + + uint8_t *(*alloc_shm)(struct wsi_image *image, unsigned size); +}; + struct wsi_image { VkImage image; VkDeviceMemory memory; @@ -97,6 +115,15 @@ wsi_swapchain_get_present_mode(struct wsi_device *wsi, void wsi_swapchain_finish(struct wsi_swapchain *chain); +VkResult +wsi_configure_native_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + uint32_t num_modifier_lists, + const uint32_t *num_modifiers, + const uint64_t *const *modifiers, + uint8_t *(alloc_shm)(struct wsi_image *image, + unsigned size), + struct wsi_image_info *info); VkResult wsi_create_native_image(const struct wsi_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, @@ -112,6 +139,14 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, bool use_modifier, struct wsi_image *image); +VkResult +wsi_configure_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + VkExternalMemoryHandleTypeFlags handle_types, + struct wsi_image_info *info); +void +wsi_destroy_image_info(const struct wsi_swapchain *chain, + struct wsi_image_info *info); void wsi_destroy_image(const struct wsi_swapchain *chain, struct wsi_image *image);