diff options
-rw-r--r-- | lib/mesa/src/vulkan/wsi/wsi_common_drm.c | 530 |
1 files changed, 335 insertions, 195 deletions
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_drm.c b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c index 72af5b2c8..1f81a92ff 100644 --- a/lib/mesa/src/vulkan/wsi/wsi_common_drm.c +++ b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c @@ -22,11 +22,9 @@ */ #include "wsi_common_private.h" -#include "wsi_common_drm.h" #include "util/macros.h" #include "util/os_file.h" #include "util/xmlconfig.h" -#include "vk_format.h" #include "vk_util.h" #include "drm-uapi/drm_fourcc.h" @@ -37,35 +35,8 @@ #include <xf86drm.h> bool -wsi_common_drm_devices_equal(int fd_a, int fd_b) -{ - drmDevicePtr device_a, device_b; - int ret; - - ret = drmGetDevice2(fd_a, 0, &device_a); - if (ret) - return false; - - ret = drmGetDevice2(fd_b, 0, &device_b); - if (ret) { - drmFreeDevice(&device_a); - return false; - } - - bool result = drmDevicesEqual(device_a, device_b); - - drmFreeDevice(&device_a); - drmFreeDevice(&device_b); - - return result; -} - -bool wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd) { - if (wsi->can_present_on_device) - return wsi->can_present_on_device(wsi->pdevice, drm_fd); - drmDevicePtr fd_device; int ret = drmGetDevice2(drm_fd, 0, &fd_device); if (ret) @@ -91,82 +62,102 @@ wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd) static uint32_t select_memory_type(const struct wsi_device *wsi, - bool want_device_local, + VkMemoryPropertyFlags props, uint32_t type_bits) { - assert(type_bits); - - bool all_local = true; for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) { const VkMemoryType type = wsi->memory_props.memoryTypes[i]; - bool local = type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - - if ((type_bits & (1 << i)) && local == want_device_local) + if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props) return i; - all_local &= local; - } - - /* ignore want_device_local when all memory types are device-local */ - if (all_local) { - assert(!want_device_local); - return ffs(type_bits) - 1; } unreachable("No memory type found"); } static uint32_t -prime_select_buffer_memory_type(const struct wsi_device *wsi, - uint32_t type_bits) -{ - return select_memory_type(wsi, false, type_bits); -} - -static uint32_t -prime_select_image_memory_type(const struct wsi_device *wsi, - uint32_t type_bits) +vk_format_size(VkFormat format) { - return select_memory_type(wsi, true, type_bits); -} - -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]; + switch (format) { + case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_B8G8R8A8_SRGB: + return 4; + default: + unreachable("Unknown WSI Format"); } - return NULL; } -static VkResult -wsi_create_native_image_mem(const struct wsi_swapchain *chain, - const struct wsi_image_info *info, - struct wsi_image *image); - 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) +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, + struct wsi_image *image) { const struct wsi_device *wsi = chain->wsi; + VkResult result; - VkExternalMemoryHandleTypeFlags handle_type = - wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT : - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + memset(image, 0, sizeof(*image)); + for (int i = 0; i < ARRAY_SIZE(image->fds); i++) + image->fds[i] = -1; + + VkImageCreateInfo image_info = { + .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 = 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); + } + + struct wsi_image_create_info image_wsi_info; + 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 */ - info->wsi.scanout = true; + image_wsi_info = (struct wsi_image_create_info) { + .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, + .scanout = true, + }; + __vk_append_struct(&image_info, &image_wsi_info); } else { /* The winsys can't request modifiers if we don't support them. */ assert(wsi->supports_modifiers); @@ -181,15 +172,17 @@ wsi_configure_native_image(const struct wsi_swapchain *chain, pCreateInfo->imageFormat, &format_props); assert(modifier_props_list.drmFormatModifierCount > 0); - 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 = info->modifier_props; + 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; + } + + modifier_props_list.pDrmFormatModifierProperties = modifier_props; wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, pCreateInfo->imageFormat, &format_props); @@ -197,11 +190,11 @@ wsi_configure_native_image(const struct wsi_swapchain *chain, /* Call GetImageFormatProperties with every modifier and filter the list * down to those that we know work. */ - info->modifier_prop_count = 0; + 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 = info->modifier_props[i].drmFormatModifier, + .drmFormatModifier = modifier_props[i].drmFormatModifier, .sharingMode = pCreateInfo->imageSharingMode, .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, @@ -212,12 +205,12 @@ wsi_configure_native_image(const struct wsi_swapchain *chain, .type = VK_IMAGE_TYPE_2D, .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, .usage = pCreateInfo->imageUsage, - .flags = info->create.flags, + .flags = image_info.flags, }; VkImageFormatListCreateInfoKHR format_list; - if (info->create.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { - format_list = info->format_list; + if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { + format_list = image_format_list; format_list.pNext = NULL; __vk_append_struct(&format_info, &format_list); } @@ -231,27 +224,33 @@ wsi_configure_native_image(const struct wsi_swapchain *chain, &format_info, &format_props); if (result == VK_SUCCESS) - info->modifier_props[info->modifier_prop_count++] = info->modifier_props[i]; + modifier_props[modifier_prop_count++] = 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]); - 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_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; + } - uint32_t image_modifier_count = 0; + 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++) { - if (get_modifier_props(info, modifiers[l][i])) - image_modifiers[image_modifier_count++] = 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]; + } } /* We only want to take the modifiers from the first list */ @@ -260,57 +259,30 @@ wsi_configure_native_image(const struct wsi_swapchain *chain, } if (image_modifier_count > 0) { - info->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - info->drm_mod_list = (VkImageDrmFormatModifierListCreateInfoEXT) { + image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, .drmFormatModifierCount = image_modifier_count, .pDrmFormatModifiers = image_modifiers, }; - image_modifiers = NULL; - __vk_append_struct(&info->create, &info->drm_mod_list); + image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + __vk_append_struct(&image_info, &image_modifier_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"); - goto fail_oom; + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; } } - info->alloc_shm = alloc_shm; - info->create_mem = wsi_create_native_image_mem; - - 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; + result = wsi->CreateImage(chain->device, &image_info, + &chain->alloc, &image->image); + if (result != VK_SUCCESS) + goto fail; VkMemoryRequirements reqs; wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); - void *sw_host_ptr = NULL; - if (info->alloc_shm) { - VkSubresourceLayout layout; - - wsi->GetImageSubresourceLayout(chain->device, image->image, - &(VkImageSubresource) { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .arrayLayer = 0, - }, &layout); - sw_host_ptr = info->alloc_shm(image, layout.size); - } - const struct wsi_memory_allocate_info memory_wsi_info = { .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, .pNext = NULL, @@ -319,8 +291,7 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, const VkExportMemoryAllocateInfo memory_export_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, .pNext = &memory_wsi_info, - .handleTypes = wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT : - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, @@ -328,22 +299,22 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, .image = image->image, .buffer = VK_NULL_HANDLE, }; - const VkImportMemoryHostPointerInfoEXT host_ptr_info = { - .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, - .pNext = &memory_dedicated_info, - .pHostPointer = sw_host_ptr, - .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, - }; const VkMemoryAllocateInfo memory_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = sw_host_ptr ? (void *)&host_ptr_info : (void *)&memory_dedicated_info, + .pNext = &memory_dedicated_info, .allocationSize = reqs.size, - .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits), + .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + reqs.memoryTypeBits), }; result = wsi->AllocateMemory(chain->device, &memory_info, &chain->alloc, &image->memory); if (result != VK_SUCCESS) - return result; + goto fail; + + result = wsi->BindImageMemory(chain->device, image->image, + image->memory, 0); + if (result != VK_SUCCESS) + goto fail; int fd = -1; if (!wsi->sw) { @@ -356,10 +327,10 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd); if (result != VK_SUCCESS) - return result; + goto fail; } - if (!wsi->sw && info->drm_mod_list.drmFormatModifierCount > 0) { + if (!wsi->sw && num_modifier_lists > 0) { VkImageDrmFormatModifierPropertiesEXT image_mod_props = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, }; @@ -368,14 +339,17 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, &image_mod_props); if (result != VK_SUCCESS) { close(fd); - return result; + goto fail; } image->drm_modifier = image_mod_props.drmFormatModifier; assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID); - const struct VkDrmFormatModifierPropertiesEXT *mod_props = - get_modifier_props(info, image->drm_modifier); - image->num_planes = mod_props->drmFormatModifierPlaneCount; + 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; + } + } for (uint32_t p = 0; p < image->num_planes; p++) { const VkImageSubresource image_subresource = { @@ -397,7 +371,8 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, for (uint32_t i = 0; i < p; i++) close(image->fds[i]); - return VK_ERROR_OUT_OF_HOST_MEMORY; + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; } } } @@ -419,63 +394,228 @@ wsi_create_native_image_mem(const struct wsi_swapchain *chain, image->fds[0] = fd; } + vk_free(&chain->alloc, modifier_props); + vk_free(&chain->alloc, image_modifiers); + return VK_SUCCESS; + +fail: + vk_free(&chain->alloc, modifier_props); + vk_free(&chain->alloc, image_modifiers); + wsi_destroy_image(chain, image); + + return result; +} + +static inline uint32_t +align_u32(uint32_t v, uint32_t a) +{ + assert(a != 0 && a == (a & -a)); + return (v + a - 1) & ~(a - 1); } #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256 -static VkResult -wsi_create_prime_image_mem(const struct wsi_swapchain *chain, - const struct wsi_image_info *info, - struct wsi_image *image) +VkResult +wsi_create_prime_image(const struct wsi_swapchain *chain, + const VkSwapchainCreateInfoKHR *pCreateInfo, + bool use_modifier, + struct wsi_image *image) { const struct wsi_device *wsi = chain->wsi; - VkResult result = - wsi_create_buffer_image_mem(chain, info, image, - VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, - true); + VkResult result; + + memset(image, 0, sizeof(*image)); + + const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat); + const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp, + WSI_PRIME_LINEAR_STRIDE_ALIGN); + + uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height; + linear_size = align_u32(linear_size, 4096); + + const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + .pNext = NULL, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + const VkBufferCreateInfo prime_buffer_info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = &prime_buffer_external_info, + .size = linear_size, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + result = wsi->CreateBuffer(chain->device, &prime_buffer_info, + &chain->alloc, &image->prime.buffer); if (result != VK_SUCCESS) - return result; + goto fail; + + VkMemoryRequirements reqs; + wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs); + assert(reqs.size <= linear_size); + + const struct wsi_memory_allocate_info memory_wsi_info = { + .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, + .pNext = NULL, + .implicit_sync = true, + }; + const VkExportMemoryAllocateInfo prime_memory_export_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, + .pNext = &memory_wsi_info, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = &prime_memory_export_info, + .image = VK_NULL_HANDLE, + .buffer = image->prime.buffer, + }; + const VkMemoryAllocateInfo prime_memory_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = &prime_memory_dedicated_info, + .allocationSize = linear_size, + .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits), + }; + result = wsi->AllocateMemory(chain->device, &prime_memory_info, + &chain->alloc, &image->prime.memory); + if (result != VK_SUCCESS) + goto fail; + + result = wsi->BindBufferMemory(chain->device, image->prime.buffer, + image->prime.memory, 0); + if (result != VK_SUCCESS) + goto fail; + + const VkImageCreateInfo image_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = NULL, + .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 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + .sharingMode = pCreateInfo->imageSharingMode, + .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, + .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; + result = wsi->CreateImage(chain->device, &image_info, + &chain->alloc, &image->image); + if (result != VK_SUCCESS) + goto fail; + + wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); + + const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = NULL, + .image = image->image, + .buffer = VK_NULL_HANDLE, + }; + const VkMemoryAllocateInfo memory_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = &memory_dedicated_info, + .allocationSize = reqs.size, + .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + reqs.memoryTypeBits), + }; + 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; + + image->prime.blit_cmd_buffers = + vk_zalloc(&chain->alloc, + sizeof(VkCommandBuffer) * wsi->queue_family_count, 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!image->prime.blit_cmd_buffers) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + + for (uint32_t i = 0; i < wsi->queue_family_count; i++) { + const VkCommandBufferAllocateInfo cmd_buffer_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .pNext = NULL, + .commandPool = chain->cmd_pools[i], + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info, + &image->prime.blit_cmd_buffers[i]); + if (result != VK_SUCCESS) + goto fail; + + const VkCommandBufferBeginInfo begin_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info); + + struct VkBufferImageCopy buffer_image_copy = { + .bufferOffset = 0, + .bufferRowLength = linear_stride / cpp, + .bufferImageHeight = 0, + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .imageOffset = { .x = 0, .y = 0, .z = 0 }, + .imageExtent = { + .width = pCreateInfo->imageExtent.width, + .height = pCreateInfo->imageExtent.height, + .depth = 1, + }, + }; + wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i], + image->image, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + image->prime.buffer, + 1, &buffer_image_copy); + + result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]); + if (result != VK_SUCCESS) + goto fail; + } const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, .pNext = NULL, - .memory = image->buffer.memory, + .memory = image->prime.memory, .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; int fd; result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd); if (result != VK_SUCCESS) - return result; + goto fail; - image->drm_modifier = info->prime_use_linear_modifier ? - DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID; + image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID; + image->num_planes = 1; + image->sizes[0] = linear_size; + image->row_pitches[0] = linear_stride; + image->offsets[0] = 0; image->fds[0] = fd; return VK_SUCCESS; -} -VkResult -wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain, - const VkSwapchainCreateInfoKHR *pCreateInfo, - bool use_modifier, - struct wsi_image_info *info) -{ - VkResult result = - wsi_configure_buffer_image(chain, pCreateInfo, info); - if (result != VK_SUCCESS) - return result; - - info->prime_use_linear_modifier = use_modifier; - - const uint32_t cpp = vk_format_get_blocksize(info->create.format); - info->linear_stride = ALIGN_POT(info->create.extent.width * cpp, - WSI_PRIME_LINEAR_STRIDE_ALIGN); - info->size_align = 4096; +fail: + wsi_destroy_image(chain, image); - info->create_mem = wsi_create_prime_image_mem; - info->select_buffer_memory_type = prime_select_buffer_memory_type; - info->select_image_memory_type = prime_select_image_memory_type; - - return VK_SUCCESS; + return result; } + |