Path: blob/21.2-virgl/src/vulkan/wsi/wsi_common_drm.c
7393 views
/*1* Copyright © 2017 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "wsi_common_private.h"24#include "util/macros.h"25#include "util/os_file.h"26#include "util/xmlconfig.h"27#include "vk_util.h"28#include "drm-uapi/drm_fourcc.h"2930#include <time.h>31#include <unistd.h>32#include <stdlib.h>33#include <stdio.h>34#include <xf86drm.h>3536bool37wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)38{39if (wsi->can_present_on_device)40return wsi->can_present_on_device(wsi->pdevice, drm_fd);4142drmDevicePtr fd_device;43int ret = drmGetDevice2(drm_fd, 0, &fd_device);44if (ret)45return false;4647bool match = false;48switch (fd_device->bustype) {49case DRM_BUS_PCI:50match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&51wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&52wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&53wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;54break;5556default:57break;58}5960drmFreeDevice(&fd_device);6162return match;63}6465static uint32_t66select_memory_type(const struct wsi_device *wsi,67bool want_device_local,68uint32_t type_bits)69{70assert(type_bits);7172bool all_local = true;73for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {74const VkMemoryType type = wsi->memory_props.memoryTypes[i];75bool local = type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;7677if ((type_bits & (1 << i)) && local == want_device_local)78return i;79all_local &= local;80}8182/* ignore want_device_local when all memory types are device-local */83if (all_local) {84assert(!want_device_local);85return ffs(type_bits) - 1;86}8788unreachable("No memory type found");89}9091static uint32_t92vk_format_size(VkFormat format)93{94switch (format) {95case VK_FORMAT_B8G8R8A8_UNORM:96case VK_FORMAT_B8G8R8A8_SRGB:97return 4;98default:99unreachable("Unknown WSI Format");100}101}102103VkResult104wsi_create_native_image(const struct wsi_swapchain *chain,105const VkSwapchainCreateInfoKHR *pCreateInfo,106uint32_t num_modifier_lists,107const uint32_t *num_modifiers,108const uint64_t *const *modifiers,109struct wsi_image *image)110{111const struct wsi_device *wsi = chain->wsi;112VkResult result;113114memset(image, 0, sizeof(*image));115for (int i = 0; i < ARRAY_SIZE(image->fds); i++)116image->fds[i] = -1;117118struct wsi_image_create_info image_wsi_info = {119.sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,120};121VkImageCreateInfo image_info = {122.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,123.pNext = &image_wsi_info,124.flags = 0,125.imageType = VK_IMAGE_TYPE_2D,126.format = pCreateInfo->imageFormat,127.extent = {128.width = pCreateInfo->imageExtent.width,129.height = pCreateInfo->imageExtent.height,130.depth = 1,131},132.mipLevels = 1,133.arrayLayers = 1,134.samples = VK_SAMPLE_COUNT_1_BIT,135.tiling = VK_IMAGE_TILING_OPTIMAL,136.usage = pCreateInfo->imageUsage,137.sharingMode = pCreateInfo->imageSharingMode,138.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,139.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,140.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,141};142143VkImageFormatListCreateInfoKHR image_format_list;144if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {145image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |146VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;147148const VkImageFormatListCreateInfoKHR *format_list =149vk_find_struct_const(pCreateInfo->pNext,150IMAGE_FORMAT_LIST_CREATE_INFO_KHR);151152#ifndef NDEBUG153assume(format_list && format_list->viewFormatCount > 0);154bool format_found = false;155for (int i = 0; i < format_list->viewFormatCount; i++)156if (pCreateInfo->imageFormat == format_list->pViewFormats[i])157format_found = true;158assert(format_found);159#endif160161image_format_list = *format_list;162image_format_list.pNext = NULL;163__vk_append_struct(&image_info, &image_format_list);164}165166VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;167168uint32_t image_modifier_count = 0, modifier_prop_count = 0;169struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;170uint64_t *image_modifiers = NULL;171if (num_modifier_lists == 0) {172/* If we don't have modifiers, fall back to the legacy "scanout" flag */173image_wsi_info.scanout = true;174} else {175/* The winsys can't request modifiers if we don't support them. */176assert(wsi->supports_modifiers);177struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {178.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,179};180VkFormatProperties2 format_props = {181.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,182.pNext = &modifier_props_list,183};184wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,185pCreateInfo->imageFormat,186&format_props);187assert(modifier_props_list.drmFormatModifierCount > 0);188modifier_props = vk_alloc(&chain->alloc,189sizeof(*modifier_props) *190modifier_props_list.drmFormatModifierCount,1918,192VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);193if (!modifier_props) {194result = VK_ERROR_OUT_OF_HOST_MEMORY;195goto fail;196}197198modifier_props_list.pDrmFormatModifierProperties = modifier_props;199wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,200pCreateInfo->imageFormat,201&format_props);202203/* Call GetImageFormatProperties with every modifier and filter the list204* down to those that we know work.205*/206modifier_prop_count = 0;207for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {208VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {209.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,210.drmFormatModifier = modifier_props[i].drmFormatModifier,211.sharingMode = pCreateInfo->imageSharingMode,212.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,213.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,214};215VkPhysicalDeviceImageFormatInfo2 format_info = {216.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,217.format = pCreateInfo->imageFormat,218.type = VK_IMAGE_TYPE_2D,219.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,220.usage = pCreateInfo->imageUsage,221.flags = image_info.flags,222};223224VkImageFormatListCreateInfoKHR format_list;225if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {226format_list = image_format_list;227format_list.pNext = NULL;228__vk_append_struct(&format_info, &format_list);229}230231VkImageFormatProperties2 format_props = {232.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,233.pNext = NULL,234};235__vk_append_struct(&format_info, &mod_info);236result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,237&format_info,238&format_props);239if (result == VK_SUCCESS)240modifier_props[modifier_prop_count++] = modifier_props[i];241}242243uint32_t max_modifier_count = 0;244for (uint32_t l = 0; l < num_modifier_lists; l++)245max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);246247image_modifiers = vk_alloc(&chain->alloc,248sizeof(*image_modifiers) *249max_modifier_count,2508,251VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);252if (!image_modifiers) {253result = VK_ERROR_OUT_OF_HOST_MEMORY;254goto fail;255}256257image_modifier_count = 0;258for (uint32_t l = 0; l < num_modifier_lists; l++) {259/* Walk the modifier lists and construct a list of supported260* modifiers.261*/262for (uint32_t i = 0; i < num_modifiers[l]; i++) {263for (uint32_t j = 0; j < modifier_prop_count; j++) {264if (modifier_props[j].drmFormatModifier == modifiers[l][i])265image_modifiers[image_modifier_count++] = modifiers[l][i];266}267}268269/* We only want to take the modifiers from the first list */270if (image_modifier_count > 0)271break;272}273274if (image_modifier_count > 0) {275image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {276.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,277.drmFormatModifierCount = image_modifier_count,278.pDrmFormatModifiers = image_modifiers,279};280image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;281__vk_append_struct(&image_info, &image_modifier_list);282} else {283/* TODO: Add a proper error here */284assert(!"Failed to find a supported modifier! This should never "285"happen because LINEAR should always be available");286result = VK_ERROR_OUT_OF_HOST_MEMORY;287goto fail;288}289}290291result = wsi->CreateImage(chain->device, &image_info,292&chain->alloc, &image->image);293if (result != VK_SUCCESS)294goto fail;295296VkMemoryRequirements reqs;297wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);298299const struct wsi_memory_allocate_info memory_wsi_info = {300.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,301.pNext = NULL,302.implicit_sync = true,303};304const VkExportMemoryAllocateInfo memory_export_info = {305.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,306.pNext = &memory_wsi_info,307.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,308};309const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {310.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,311.pNext = &memory_export_info,312.image = image->image,313.buffer = VK_NULL_HANDLE,314};315const VkMemoryAllocateInfo memory_info = {316.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,317.pNext = &memory_dedicated_info,318.allocationSize = reqs.size,319.memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),320};321result = wsi->AllocateMemory(chain->device, &memory_info,322&chain->alloc, &image->memory);323if (result != VK_SUCCESS)324goto fail;325326result = wsi->BindImageMemory(chain->device, image->image,327image->memory, 0);328if (result != VK_SUCCESS)329goto fail;330331int fd = -1;332if (!wsi->sw) {333const VkMemoryGetFdInfoKHR memory_get_fd_info = {334.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,335.pNext = NULL,336.memory = image->memory,337.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,338};339340result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);341if (result != VK_SUCCESS)342goto fail;343}344345if (!wsi->sw && num_modifier_lists > 0) {346VkImageDrmFormatModifierPropertiesEXT image_mod_props = {347.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,348};349result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,350image->image,351&image_mod_props);352if (result != VK_SUCCESS) {353close(fd);354goto fail;355}356image->drm_modifier = image_mod_props.drmFormatModifier;357assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);358359for (uint32_t j = 0; j < modifier_prop_count; j++) {360if (modifier_props[j].drmFormatModifier == image->drm_modifier) {361image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;362break;363}364}365366for (uint32_t p = 0; p < image->num_planes; p++) {367const VkImageSubresource image_subresource = {368.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,369.mipLevel = 0,370.arrayLayer = 0,371};372VkSubresourceLayout image_layout;373wsi->GetImageSubresourceLayout(chain->device, image->image,374&image_subresource, &image_layout);375image->sizes[p] = image_layout.size;376image->row_pitches[p] = image_layout.rowPitch;377image->offsets[p] = image_layout.offset;378if (p == 0) {379image->fds[p] = fd;380} else {381image->fds[p] = os_dupfd_cloexec(fd);382if (image->fds[p] == -1) {383for (uint32_t i = 0; i < p; i++)384close(image->fds[i]);385386result = VK_ERROR_OUT_OF_HOST_MEMORY;387goto fail;388}389}390}391} else {392const VkImageSubresource image_subresource = {393.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,394.mipLevel = 0,395.arrayLayer = 0,396};397VkSubresourceLayout image_layout;398wsi->GetImageSubresourceLayout(chain->device, image->image,399&image_subresource, &image_layout);400401image->drm_modifier = DRM_FORMAT_MOD_INVALID;402image->num_planes = 1;403image->sizes[0] = reqs.size;404image->row_pitches[0] = image_layout.rowPitch;405image->offsets[0] = 0;406image->fds[0] = fd;407}408409vk_free(&chain->alloc, modifier_props);410vk_free(&chain->alloc, image_modifiers);411412return VK_SUCCESS;413414fail:415vk_free(&chain->alloc, modifier_props);416vk_free(&chain->alloc, image_modifiers);417wsi_destroy_image(chain, image);418419return result;420}421422static inline uint32_t423align_u32(uint32_t v, uint32_t a)424{425assert(a != 0 && a == (a & -a));426return (v + a - 1) & ~(a - 1);427}428429#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256430431VkResult432wsi_create_prime_image(const struct wsi_swapchain *chain,433const VkSwapchainCreateInfoKHR *pCreateInfo,434bool use_modifier,435struct wsi_image *image)436{437const struct wsi_device *wsi = chain->wsi;438VkResult result;439440memset(image, 0, sizeof(*image));441442const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);443const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,444WSI_PRIME_LINEAR_STRIDE_ALIGN);445446uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;447linear_size = align_u32(linear_size, 4096);448449const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {450.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,451.pNext = NULL,452.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,453};454const VkBufferCreateInfo prime_buffer_info = {455.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,456.pNext = &prime_buffer_external_info,457.size = linear_size,458.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,459.sharingMode = VK_SHARING_MODE_EXCLUSIVE,460};461result = wsi->CreateBuffer(chain->device, &prime_buffer_info,462&chain->alloc, &image->prime.buffer);463if (result != VK_SUCCESS)464goto fail;465466VkMemoryRequirements reqs;467wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);468assert(reqs.size <= linear_size);469470const struct wsi_memory_allocate_info memory_wsi_info = {471.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,472.pNext = NULL,473.implicit_sync = true,474};475const VkExportMemoryAllocateInfo prime_memory_export_info = {476.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,477.pNext = &memory_wsi_info,478.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,479};480const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {481.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,482.pNext = &prime_memory_export_info,483.image = VK_NULL_HANDLE,484.buffer = image->prime.buffer,485};486const VkMemoryAllocateInfo prime_memory_info = {487.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,488.pNext = &prime_memory_dedicated_info,489.allocationSize = linear_size,490.memoryTypeIndex = select_memory_type(wsi, false, reqs.memoryTypeBits),491};492result = wsi->AllocateMemory(chain->device, &prime_memory_info,493&chain->alloc, &image->prime.memory);494if (result != VK_SUCCESS)495goto fail;496497result = wsi->BindBufferMemory(chain->device, image->prime.buffer,498image->prime.memory, 0);499if (result != VK_SUCCESS)500goto fail;501502const struct wsi_image_create_info image_wsi_info = {503.sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,504.prime_blit_buffer = image->prime.buffer,505};506const VkImageCreateInfo image_info = {507.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,508.pNext = &image_wsi_info,509.flags = 0,510.imageType = VK_IMAGE_TYPE_2D,511.format = pCreateInfo->imageFormat,512.extent = {513.width = pCreateInfo->imageExtent.width,514.height = pCreateInfo->imageExtent.height,515.depth = 1,516},517.mipLevels = 1,518.arrayLayers = 1,519.samples = VK_SAMPLE_COUNT_1_BIT,520.tiling = VK_IMAGE_TILING_OPTIMAL,521.usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,522.sharingMode = pCreateInfo->imageSharingMode,523.queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,524.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,525.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,526};527result = wsi->CreateImage(chain->device, &image_info,528&chain->alloc, &image->image);529if (result != VK_SUCCESS)530goto fail;531532wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);533534const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {535.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,536.pNext = NULL,537.image = image->image,538.buffer = VK_NULL_HANDLE,539};540const VkMemoryAllocateInfo memory_info = {541.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,542.pNext = &memory_dedicated_info,543.allocationSize = reqs.size,544.memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),545};546result = wsi->AllocateMemory(chain->device, &memory_info,547&chain->alloc, &image->memory);548if (result != VK_SUCCESS)549goto fail;550551result = wsi->BindImageMemory(chain->device, image->image,552image->memory, 0);553if (result != VK_SUCCESS)554goto fail;555556image->prime.blit_cmd_buffers =557vk_zalloc(&chain->alloc,558sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,559VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);560if (!image->prime.blit_cmd_buffers) {561result = VK_ERROR_OUT_OF_HOST_MEMORY;562goto fail;563}564565for (uint32_t i = 0; i < wsi->queue_family_count; i++) {566const VkCommandBufferAllocateInfo cmd_buffer_info = {567.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,568.pNext = NULL,569.commandPool = chain->cmd_pools[i],570.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,571.commandBufferCount = 1,572};573result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,574&image->prime.blit_cmd_buffers[i]);575if (result != VK_SUCCESS)576goto fail;577578const VkCommandBufferBeginInfo begin_info = {579.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,580};581wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);582583struct VkBufferImageCopy buffer_image_copy = {584.bufferOffset = 0,585.bufferRowLength = linear_stride / cpp,586.bufferImageHeight = 0,587.imageSubresource = {588.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,589.mipLevel = 0,590.baseArrayLayer = 0,591.layerCount = 1,592},593.imageOffset = { .x = 0, .y = 0, .z = 0 },594.imageExtent = {595.width = pCreateInfo->imageExtent.width,596.height = pCreateInfo->imageExtent.height,597.depth = 1,598},599};600wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],601image->image,602VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,603image->prime.buffer,6041, &buffer_image_copy);605606result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);607if (result != VK_SUCCESS)608goto fail;609}610611const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {612.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,613.pNext = NULL,614.memory = image->prime.memory,615.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,616};617int fd;618result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);619if (result != VK_SUCCESS)620goto fail;621622image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;623image->num_planes = 1;624image->sizes[0] = linear_size;625image->row_pitches[0] = linear_stride;626image->offsets[0] = 0;627image->fds[0] = fd;628629return VK_SUCCESS;630631fail:632wsi_destroy_image(chain, image);633634return result;635}636637638639