Path: blob/21.2-virgl/src/virtio/vulkan/vn_image.c
4560 views
/*1* Copyright 2019 Google LLC2* SPDX-License-Identifier: MIT3*4* based in part on anv and radv which are:5* Copyright © 2015 Intel Corporation6* Copyright © 2016 Red Hat.7* Copyright © 2016 Bas Nieuwenhuizen8*/910#include "vn_image.h"1112#include "venus-protocol/vn_protocol_driver_image.h"13#include "venus-protocol/vn_protocol_driver_image_view.h"14#include "venus-protocol/vn_protocol_driver_sampler.h"15#include "venus-protocol/vn_protocol_driver_sampler_ycbcr_conversion.h"1617#include "vn_android.h"18#include "vn_device.h"19#include "vn_device_memory.h"2021static void22vn_image_init_memory_requirements(struct vn_image *img,23struct vn_device *dev,24const VkImageCreateInfo *create_info)25{26uint32_t plane_count = 1;27if (create_info->flags & VK_IMAGE_CREATE_DISJOINT_BIT) {28/* TODO VkDrmFormatModifierPropertiesEXT::drmFormatModifierPlaneCount */29assert(create_info->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);3031switch (create_info->format) {32case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:33case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:34case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:35case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:36case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:37case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:38case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:39case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:40plane_count = 2;41break;42case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:43case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:44case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:45case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:46case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:47case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:48case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:49case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:50case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:51case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:52case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:53case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:54plane_count = 3;55break;56default:57plane_count = 1;58break;59}60}61assert(plane_count <= ARRAY_SIZE(img->memory_requirements));6263/* TODO add a per-device cache for the requirements */64for (uint32_t i = 0; i < plane_count; i++) {65img->memory_requirements[i].sType =66VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;67img->memory_requirements[i].pNext = &img->dedicated_requirements[i];68img->dedicated_requirements[i].sType =69VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;70img->dedicated_requirements[i].pNext = NULL;71}7273VkDevice dev_handle = vn_device_to_handle(dev);74VkImage img_handle = vn_image_to_handle(img);75if (plane_count == 1) {76vn_call_vkGetImageMemoryRequirements2(77dev->instance, dev_handle,78&(VkImageMemoryRequirementsInfo2){79.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,80.image = img_handle,81},82&img->memory_requirements[0]);8384/* AHB backed image requires dedicated allocation */85if (img->deferred_info) {86img->dedicated_requirements[0].prefersDedicatedAllocation = VK_TRUE;87img->dedicated_requirements[0].requiresDedicatedAllocation = VK_TRUE;88}89} else {90for (uint32_t i = 0; i < plane_count; i++) {91vn_call_vkGetImageMemoryRequirements2(92dev->instance, dev_handle,93&(VkImageMemoryRequirementsInfo2){94.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,95.pNext =96&(VkImagePlaneMemoryRequirementsInfo){97.sType =98VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO,99.planeAspect = VK_IMAGE_ASPECT_PLANE_0_BIT << i,100},101.image = img_handle,102},103&img->memory_requirements[i]);104}105}106}107108static VkResult109vn_image_store_deferred_create_info(110const VkImageCreateInfo *create_info,111const VkAllocationCallbacks *alloc,112struct vn_image_create_deferred_info **out_info)113{114struct vn_image_create_deferred_info *info = NULL;115VkBaseOutStructure *dst = NULL;116117info = vk_zalloc(alloc, sizeof(*info), VN_DEFAULT_ALIGN,118VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);119if (!info)120return VK_ERROR_OUT_OF_HOST_MEMORY;121122info->create = *create_info;123dst = (void *)&info->create;124125vk_foreach_struct_const(src, create_info->pNext) {126void *pnext = NULL;127switch (src->sType) {128case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO:129memcpy(&info->list, src, sizeof(info->list));130pnext = &info->list;131break;132case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:133memcpy(&info->stencil, src, sizeof(info->stencil));134pnext = &info->stencil;135break;136default:137break;138}139140if (pnext) {141dst->pNext = pnext;142dst = pnext;143}144}145dst->pNext = NULL;146147*out_info = info;148149return VK_SUCCESS;150}151152static VkResult153vn_image_init(struct vn_device *dev,154const VkImageCreateInfo *create_info,155struct vn_image *img)156{157VkDevice device = vn_device_to_handle(dev);158VkImage image = vn_image_to_handle(img);159VkResult result = VK_SUCCESS;160161img->sharing_mode = create_info->sharingMode;162163/* TODO async */164result =165vn_call_vkCreateImage(dev->instance, device, create_info, NULL, &image);166if (result != VK_SUCCESS)167return result;168169vn_image_init_memory_requirements(img, dev, create_info);170171return VK_SUCCESS;172}173174VkResult175vn_image_create(struct vn_device *dev,176const VkImageCreateInfo *create_info,177const VkAllocationCallbacks *alloc,178struct vn_image **out_img)179{180struct vn_image *img = NULL;181VkResult result = VK_SUCCESS;182183img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,184VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);185if (!img)186return VK_ERROR_OUT_OF_HOST_MEMORY;187188vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);189190result = vn_image_init(dev, create_info, img);191if (result != VK_SUCCESS) {192vk_free(alloc, img);193return result;194}195196*out_img = img;197198return VK_SUCCESS;199}200201VkResult202vn_image_init_deferred(struct vn_device *dev,203const VkImageCreateInfo *create_info,204struct vn_image *img)205{206return vn_image_init(dev, create_info, img);207}208209VkResult210vn_image_create_deferred(struct vn_device *dev,211const VkImageCreateInfo *create_info,212const VkAllocationCallbacks *alloc,213struct vn_image **out_img)214{215struct vn_image *img = NULL;216VkResult result = VK_SUCCESS;217218img = vk_zalloc(alloc, sizeof(*img), VN_DEFAULT_ALIGN,219VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);220if (!img)221return VK_ERROR_OUT_OF_HOST_MEMORY;222223vn_object_base_init(&img->base, VK_OBJECT_TYPE_IMAGE, &dev->base);224225result = vn_image_store_deferred_create_info(create_info, alloc,226&img->deferred_info);227if (result != VK_SUCCESS) {228vk_free(alloc, img);229return result;230}231232*out_img = img;233234return VK_SUCCESS;235}236237/* image commands */238239VkResult240vn_CreateImage(VkDevice device,241const VkImageCreateInfo *pCreateInfo,242const VkAllocationCallbacks *pAllocator,243VkImage *pImage)244{245struct vn_device *dev = vn_device_from_handle(device);246const VkAllocationCallbacks *alloc =247pAllocator ? pAllocator : &dev->base.base.alloc;248struct vn_image *img;249VkResult result;250251const struct wsi_image_create_info *wsi_info =252vn_wsi_find_wsi_image_create_info(pCreateInfo);253const VkNativeBufferANDROID *anb_info =254vn_android_find_native_buffer(pCreateInfo);255const VkExternalMemoryImageCreateInfo *external_info =256vk_find_struct_const(pCreateInfo->pNext,257EXTERNAL_MEMORY_IMAGE_CREATE_INFO);258const bool ahb_info =259external_info &&260external_info->handleTypes ==261VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;262263if (wsi_info) {264result = vn_wsi_create_image(dev, pCreateInfo, wsi_info, alloc, &img);265} else if (anb_info) {266result =267vn_android_image_from_anb(dev, pCreateInfo, anb_info, alloc, &img);268} else if (ahb_info) {269result = vn_android_image_from_ahb(dev, pCreateInfo, alloc, &img);270} else {271result = vn_image_create(dev, pCreateInfo, alloc, &img);272}273274if (result != VK_SUCCESS)275return vn_error(dev->instance, result);276277*pImage = vn_image_to_handle(img);278return VK_SUCCESS;279}280281void282vn_DestroyImage(VkDevice device,283VkImage image,284const VkAllocationCallbacks *pAllocator)285{286struct vn_device *dev = vn_device_from_handle(device);287struct vn_image *img = vn_image_from_handle(image);288const VkAllocationCallbacks *alloc =289pAllocator ? pAllocator : &dev->base.base.alloc;290291if (!img)292return;293294if (img->private_memory != VK_NULL_HANDLE)295vn_FreeMemory(device, img->private_memory, pAllocator);296297vn_async_vkDestroyImage(dev->instance, device, image, NULL);298299if (img->deferred_info)300vk_free(alloc, img->deferred_info);301302vn_object_base_fini(&img->base);303vk_free(alloc, img);304}305306void307vn_GetImageMemoryRequirements(VkDevice device,308VkImage image,309VkMemoryRequirements *pMemoryRequirements)310{311const struct vn_image *img = vn_image_from_handle(image);312313*pMemoryRequirements = img->memory_requirements[0].memoryRequirements;314}315316void317vn_GetImageSparseMemoryRequirements(318VkDevice device,319VkImage image,320uint32_t *pSparseMemoryRequirementCount,321VkSparseImageMemoryRequirements *pSparseMemoryRequirements)322{323struct vn_device *dev = vn_device_from_handle(device);324325/* TODO per-device cache */326vn_call_vkGetImageSparseMemoryRequirements(dev->instance, device, image,327pSparseMemoryRequirementCount,328pSparseMemoryRequirements);329}330331void332vn_GetImageMemoryRequirements2(VkDevice device,333const VkImageMemoryRequirementsInfo2 *pInfo,334VkMemoryRequirements2 *pMemoryRequirements)335{336const struct vn_image *img = vn_image_from_handle(pInfo->image);337union {338VkBaseOutStructure *pnext;339VkMemoryRequirements2 *two;340VkMemoryDedicatedRequirements *dedicated;341} u = { .two = pMemoryRequirements };342343uint32_t plane = 0;344const VkImagePlaneMemoryRequirementsInfo *plane_info =345vk_find_struct_const(pInfo->pNext,346IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO);347if (plane_info) {348switch (plane_info->planeAspect) {349case VK_IMAGE_ASPECT_PLANE_1_BIT:350plane = 1;351break;352case VK_IMAGE_ASPECT_PLANE_2_BIT:353plane = 2;354break;355default:356plane = 0;357break;358}359}360361while (u.pnext) {362switch (u.pnext->sType) {363case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:364u.two->memoryRequirements =365img->memory_requirements[plane].memoryRequirements;366break;367case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:368u.dedicated->prefersDedicatedAllocation =369img->dedicated_requirements[plane].prefersDedicatedAllocation;370u.dedicated->requiresDedicatedAllocation =371img->dedicated_requirements[plane].requiresDedicatedAllocation;372break;373default:374break;375}376u.pnext = u.pnext->pNext;377}378}379380void381vn_GetImageSparseMemoryRequirements2(382VkDevice device,383const VkImageSparseMemoryRequirementsInfo2 *pInfo,384uint32_t *pSparseMemoryRequirementCount,385VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)386{387struct vn_device *dev = vn_device_from_handle(device);388389/* TODO per-device cache */390vn_call_vkGetImageSparseMemoryRequirements2(dev->instance, device, pInfo,391pSparseMemoryRequirementCount,392pSparseMemoryRequirements);393}394395VkResult396vn_BindImageMemory(VkDevice device,397VkImage image,398VkDeviceMemory memory,399VkDeviceSize memoryOffset)400{401struct vn_device *dev = vn_device_from_handle(device);402struct vn_device_memory *mem = vn_device_memory_from_handle(memory);403404if (mem->base_memory) {405memory = vn_device_memory_to_handle(mem->base_memory);406memoryOffset += mem->base_offset;407}408409vn_async_vkBindImageMemory(dev->instance, device, image, memory,410memoryOffset);411412return VK_SUCCESS;413}414415VkResult416vn_BindImageMemory2(VkDevice device,417uint32_t bindInfoCount,418const VkBindImageMemoryInfo *pBindInfos)419{420struct vn_device *dev = vn_device_from_handle(device);421const VkAllocationCallbacks *alloc = &dev->base.base.alloc;422423VkBindImageMemoryInfo *local_infos = NULL;424for (uint32_t i = 0; i < bindInfoCount; i++) {425const VkBindImageMemoryInfo *info = &pBindInfos[i];426struct vn_device_memory *mem =427vn_device_memory_from_handle(info->memory);428/* TODO handle VkBindImageMemorySwapchainInfoKHR */429if (!mem || !mem->base_memory)430continue;431432if (!local_infos) {433const size_t size = sizeof(*local_infos) * bindInfoCount;434local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN,435VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);436if (!local_infos)437return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);438439memcpy(local_infos, pBindInfos, size);440}441442local_infos[i].memory = vn_device_memory_to_handle(mem->base_memory);443local_infos[i].memoryOffset += mem->base_offset;444}445if (local_infos)446pBindInfos = local_infos;447448vn_async_vkBindImageMemory2(dev->instance, device, bindInfoCount,449pBindInfos);450451vk_free(alloc, local_infos);452453return VK_SUCCESS;454}455456VkResult457vn_GetImageDrmFormatModifierPropertiesEXT(458VkDevice device,459VkImage image,460VkImageDrmFormatModifierPropertiesEXT *pProperties)461{462struct vn_device *dev = vn_device_from_handle(device);463464/* TODO local cache */465return vn_call_vkGetImageDrmFormatModifierPropertiesEXT(466dev->instance, device, image, pProperties);467}468469void470vn_GetImageSubresourceLayout(VkDevice device,471VkImage image,472const VkImageSubresource *pSubresource,473VkSubresourceLayout *pLayout)474{475struct vn_device *dev = vn_device_from_handle(device);476477/* TODO local cache */478vn_call_vkGetImageSubresourceLayout(dev->instance, device, image,479pSubresource, pLayout);480}481482/* image view commands */483484VkResult485vn_CreateImageView(VkDevice device,486const VkImageViewCreateInfo *pCreateInfo,487const VkAllocationCallbacks *pAllocator,488VkImageView *pView)489{490struct vn_device *dev = vn_device_from_handle(device);491const VkAllocationCallbacks *alloc =492pAllocator ? pAllocator : &dev->base.base.alloc;493494struct vn_image_view *view =495vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,496VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);497if (!view)498return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);499500vn_object_base_init(&view->base, VK_OBJECT_TYPE_IMAGE_VIEW, &dev->base);501view->image = vn_image_from_handle(pCreateInfo->image);502503VkImageView view_handle = vn_image_view_to_handle(view);504vn_async_vkCreateImageView(dev->instance, device, pCreateInfo, NULL,505&view_handle);506507*pView = view_handle;508509return VK_SUCCESS;510}511512void513vn_DestroyImageView(VkDevice device,514VkImageView imageView,515const VkAllocationCallbacks *pAllocator)516{517struct vn_device *dev = vn_device_from_handle(device);518struct vn_image_view *view = vn_image_view_from_handle(imageView);519const VkAllocationCallbacks *alloc =520pAllocator ? pAllocator : &dev->base.base.alloc;521522if (!view)523return;524525vn_async_vkDestroyImageView(dev->instance, device, imageView, NULL);526527vn_object_base_fini(&view->base);528vk_free(alloc, view);529}530531/* sampler commands */532533VkResult534vn_CreateSampler(VkDevice device,535const VkSamplerCreateInfo *pCreateInfo,536const VkAllocationCallbacks *pAllocator,537VkSampler *pSampler)538{539struct vn_device *dev = vn_device_from_handle(device);540const VkAllocationCallbacks *alloc =541pAllocator ? pAllocator : &dev->base.base.alloc;542543struct vn_sampler *sampler =544vk_zalloc(alloc, sizeof(*sampler), VN_DEFAULT_ALIGN,545VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);546if (!sampler)547return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);548549vn_object_base_init(&sampler->base, VK_OBJECT_TYPE_SAMPLER, &dev->base);550551VkSampler sampler_handle = vn_sampler_to_handle(sampler);552vn_async_vkCreateSampler(dev->instance, device, pCreateInfo, NULL,553&sampler_handle);554555*pSampler = sampler_handle;556557return VK_SUCCESS;558}559560void561vn_DestroySampler(VkDevice device,562VkSampler _sampler,563const VkAllocationCallbacks *pAllocator)564{565struct vn_device *dev = vn_device_from_handle(device);566struct vn_sampler *sampler = vn_sampler_from_handle(_sampler);567const VkAllocationCallbacks *alloc =568pAllocator ? pAllocator : &dev->base.base.alloc;569570if (!sampler)571return;572573vn_async_vkDestroySampler(dev->instance, device, _sampler, NULL);574575vn_object_base_fini(&sampler->base);576vk_free(alloc, sampler);577}578579/* sampler YCbCr conversion commands */580581VkResult582vn_CreateSamplerYcbcrConversion(583VkDevice device,584const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,585const VkAllocationCallbacks *pAllocator,586VkSamplerYcbcrConversion *pYcbcrConversion)587{588struct vn_device *dev = vn_device_from_handle(device);589const VkAllocationCallbacks *alloc =590pAllocator ? pAllocator : &dev->base.base.alloc;591const VkExternalFormatANDROID *ext_info =592vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_FORMAT_ANDROID);593594VkSamplerYcbcrConversionCreateInfo local_info;595if (ext_info && ext_info->externalFormat) {596assert(pCreateInfo->format == VK_FORMAT_UNDEFINED);597598local_info = *pCreateInfo;599local_info.format =600vn_android_drm_format_to_vk_format(ext_info->externalFormat);601local_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;602local_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;603local_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;604local_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;605pCreateInfo = &local_info;606607assert(pCreateInfo->format != VK_FORMAT_UNDEFINED);608}609610struct vn_sampler_ycbcr_conversion *conv =611vk_zalloc(alloc, sizeof(*conv), VN_DEFAULT_ALIGN,612VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);613if (!conv)614return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);615616vn_object_base_init(&conv->base, VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,617&dev->base);618619VkSamplerYcbcrConversion conv_handle =620vn_sampler_ycbcr_conversion_to_handle(conv);621vn_async_vkCreateSamplerYcbcrConversion(dev->instance, device, pCreateInfo,622NULL, &conv_handle);623624*pYcbcrConversion = conv_handle;625626return VK_SUCCESS;627}628629void630vn_DestroySamplerYcbcrConversion(VkDevice device,631VkSamplerYcbcrConversion ycbcrConversion,632const VkAllocationCallbacks *pAllocator)633{634struct vn_device *dev = vn_device_from_handle(device);635struct vn_sampler_ycbcr_conversion *conv =636vn_sampler_ycbcr_conversion_from_handle(ycbcrConversion);637const VkAllocationCallbacks *alloc =638pAllocator ? pAllocator : &dev->base.base.alloc;639640if (!conv)641return;642643vn_async_vkDestroySamplerYcbcrConversion(dev->instance, device,644ycbcrConversion, NULL);645646vn_object_base_fini(&conv->base);647vk_free(alloc, conv);648}649650651