Path: blob/21.2-virgl/src/virtio/vulkan/vn_android.c
4560 views
/*1* Copyright 2021 Google LLC2* SPDX-License-Identifier: MIT3*4* based in part on anv and radv which are:5* Copyright © 2015 Intel Corporation6* Copyright © 2016 Red Hat7* Copyright © 2016 Bas Nieuwenhuizen8*/910#include "vn_android.h"1112#include <dlfcn.h>13#include <hardware/gralloc.h>14#include <hardware/hwvulkan.h>15#include <vndk/hardware_buffer.h>16#include <vulkan/vk_icd.h>1718#include "drm-uapi/drm_fourcc.h"19#include "util/libsync.h"20#include "util/os_file.h"2122#include "vn_buffer.h"23#include "vn_device.h"24#include "vn_device_memory.h"25#include "vn_image.h"26#include "vn_queue.h"2728static int29vn_hal_open(const struct hw_module_t *mod,30const char *id,31struct hw_device_t **dev);3233static void UNUSED34static_asserts(void)35{36STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);37}3839PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {40.common = {41.tag = HARDWARE_MODULE_TAG,42.module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,43.hal_api_version = HARDWARE_HAL_API_VERSION,44.id = HWVULKAN_HARDWARE_MODULE_ID,45.name = "Venus Vulkan HAL",46.author = "Google LLC",47.methods = &(hw_module_methods_t) {48.open = vn_hal_open,49},50},51};5253static const gralloc_module_t *gralloc = NULL;5455static int56vn_hal_close(UNUSED struct hw_device_t *dev)57{58dlclose(gralloc->common.dso);59return 0;60}6162static hwvulkan_device_t vn_hal_dev = {63.common = {64.tag = HARDWARE_DEVICE_TAG,65.version = HWVULKAN_DEVICE_API_VERSION_0_1,66.module = &HAL_MODULE_INFO_SYM.common,67.close = vn_hal_close,68},69.EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties,70.CreateInstance = vn_CreateInstance,71.GetInstanceProcAddr = vn_GetInstanceProcAddr,72};7374static int75vn_hal_open(const struct hw_module_t *mod,76const char *id,77struct hw_device_t **dev)78{79static const char CROS_GRALLOC_MODULE_NAME[] = "CrOS Gralloc";8081assert(mod == &HAL_MODULE_INFO_SYM.common);82assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);8384/* get gralloc module for gralloc buffer info query */85int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,86(const hw_module_t **)&gralloc);87if (ret) {88if (VN_DEBUG(WSI))89vn_log(NULL, "failed to open gralloc module(ret=%d)", ret);90return ret;91}9293if (VN_DEBUG(WSI))94vn_log(NULL, "opened gralloc module name: %s", gralloc->common.name);9596if (strcmp(gralloc->common.name, CROS_GRALLOC_MODULE_NAME) != 0 ||97!gralloc->perform) {98dlclose(gralloc->common.dso);99return -1;100}101102*dev = &vn_hal_dev.common;103104return 0;105}106107static uint32_t108vn_android_ahb_format_from_vk_format(VkFormat format)109{110switch (format) {111case VK_FORMAT_R8G8B8A8_UNORM:112return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;113case VK_FORMAT_R8G8B8_UNORM:114return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;115case VK_FORMAT_R5G6B5_UNORM_PACK16:116return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;117case VK_FORMAT_R16G16B16A16_SFLOAT:118return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;119case VK_FORMAT_A2B10G10R10_UNORM_PACK32:120return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;121case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:122return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;123default:124return 0;125}126}127128VkFormat129vn_android_drm_format_to_vk_format(uint32_t format)130{131switch (format) {132case DRM_FORMAT_ABGR8888:133case DRM_FORMAT_XBGR8888:134return VK_FORMAT_R8G8B8A8_UNORM;135case DRM_FORMAT_BGR888:136return VK_FORMAT_R8G8B8_UNORM;137case DRM_FORMAT_RGB565:138return VK_FORMAT_R5G6B5_UNORM_PACK16;139case DRM_FORMAT_ABGR16161616F:140return VK_FORMAT_R16G16B16A16_SFLOAT;141case DRM_FORMAT_ABGR2101010:142return VK_FORMAT_A2B10G10R10_UNORM_PACK32;143case DRM_FORMAT_YVU420:144case DRM_FORMAT_NV12:145return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;146default:147return VK_FORMAT_UNDEFINED;148}149}150151uint64_t152vn_android_get_ahb_usage(const VkImageUsageFlags usage,153const VkImageCreateFlags flags)154{155uint64_t ahb_usage = 0;156if (usage &157(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))158ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;159160if (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |161VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))162ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;163164if (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)165ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;166167if (flags & VK_IMAGE_CREATE_PROTECTED_BIT)168ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;169170/* must include at least one GPU usage flag */171if (ahb_usage == 0)172ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;173174return ahb_usage;175}176177VkResult178vn_GetSwapchainGrallocUsage2ANDROID(179VkDevice device,180VkFormat format,181VkImageUsageFlags imageUsage,182VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,183uint64_t *grallocConsumerUsage,184uint64_t *grallocProducerUsage)185{186struct vn_device *dev = vn_device_from_handle(device);187*grallocConsumerUsage = 0;188*grallocProducerUsage = 0;189190if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)191return vn_error(dev->instance, VK_ERROR_INITIALIZATION_FAILED);192193if (VN_DEBUG(WSI))194vn_log(dev->instance, "format=%d, imageUsage=0x%x", format, imageUsage);195196if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |197VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))198*grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;199200if (imageUsage &201(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |202VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))203*grallocConsumerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;204205return VK_SUCCESS;206}207208struct cros_gralloc0_buffer_info {209uint32_t drm_fourcc;210int num_fds; /* ignored */211int fds[4]; /* ignored */212uint64_t modifier;213uint32_t offset[4];214uint32_t stride[4];215};216217struct vn_android_gralloc_buffer_properties {218uint32_t drm_fourcc;219uint64_t modifier;220uint32_t offset[4];221uint32_t stride[4];222};223224static VkResult225vn_android_get_dma_buf_from_native_handle(const native_handle_t *handle,226int *out_dma_buf)227{228/* There can be multiple fds wrapped inside a native_handle_t, but we229* expect only the 1st one points to the dma_buf. For multi-planar format,230* there should only exist one dma_buf as well. The other fd(s) may point231* to shared memory used to store buffer metadata or other vendor specific232* bits.233*/234if (handle->numFds < 1) {235vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds);236return VK_ERROR_INVALID_EXTERNAL_HANDLE;237}238239if (handle->data[0] < 0) {240vn_log(NULL, "handle->data[0] < 0");241return VK_ERROR_INVALID_EXTERNAL_HANDLE;242}243244*out_dma_buf = handle->data[0];245return VK_SUCCESS;246}247248static bool249vn_android_get_gralloc_buffer_properties(250buffer_handle_t handle,251struct vn_android_gralloc_buffer_properties *out_props)252{253static const int32_t CROS_GRALLOC_DRM_GET_BUFFER_INFO = 4;254struct cros_gralloc0_buffer_info info;255if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO, handle,256&info) != 0) {257vn_log(NULL, "CROS_GRALLOC_DRM_GET_BUFFER_INFO failed");258return false;259}260261if (info.modifier == DRM_FORMAT_MOD_INVALID) {262vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID");263return false;264}265266out_props->drm_fourcc = info.drm_fourcc;267for (uint32_t i = 0; i < 4; i++) {268out_props->stride[i] = info.stride[i];269out_props->offset[i] = info.offset[i];270}271out_props->modifier = info.modifier;272273return true;274}275276static VkResult277vn_android_get_modifier_properties(struct vn_device *dev,278VkFormat format,279uint64_t modifier,280const VkAllocationCallbacks *alloc,281VkDrmFormatModifierPropertiesEXT *out_props)282{283VkPhysicalDevice physical_device =284vn_physical_device_to_handle(dev->physical_device);285VkDrmFormatModifierPropertiesListEXT mod_prop_list = {286.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,287.pNext = NULL,288.drmFormatModifierCount = 0,289.pDrmFormatModifierProperties = NULL,290};291VkFormatProperties2 format_prop = {292.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,293.pNext = &mod_prop_list,294};295VkDrmFormatModifierPropertiesEXT *mod_props = NULL;296bool modifier_found = false;297298vn_GetPhysicalDeviceFormatProperties2(physical_device, format,299&format_prop);300301if (!mod_prop_list.drmFormatModifierCount) {302vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",303format);304return VK_ERROR_INVALID_EXTERNAL_HANDLE;305}306307mod_props = vk_zalloc(308alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount,309VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);310if (!mod_props)311return VK_ERROR_OUT_OF_HOST_MEMORY;312313mod_prop_list.pDrmFormatModifierProperties = mod_props;314vn_GetPhysicalDeviceFormatProperties2(physical_device, format,315&format_prop);316317for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {318if (mod_props[i].drmFormatModifier == modifier) {319*out_props = mod_props[i];320modifier_found = true;321break;322}323}324325vk_free(alloc, mod_props);326327if (!modifier_found) {328vn_log(dev->instance,329"No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",330modifier, format);331return VK_ERROR_INVALID_EXTERNAL_HANDLE;332}333334return VK_SUCCESS;335}336337struct vn_android_image_builder {338VkImageCreateInfo create;339VkSubresourceLayout layouts[4];340VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;341VkExternalMemoryImageCreateInfo external;342};343344static VkResult345vn_android_get_image_builder(struct vn_device *dev,346const VkImageCreateInfo *create_info,347const native_handle_t *handle,348const VkAllocationCallbacks *alloc,349struct vn_android_image_builder *out_builder)350{351VkResult result = VK_SUCCESS;352struct vn_android_gralloc_buffer_properties buf_props;353VkDrmFormatModifierPropertiesEXT mod_props;354355if (!vn_android_get_gralloc_buffer_properties(handle, &buf_props))356return VK_ERROR_INVALID_EXTERNAL_HANDLE;357358result = vn_android_get_modifier_properties(359dev, create_info->format, buf_props.modifier, alloc, &mod_props);360if (result != VK_SUCCESS)361return result;362363memset(out_builder->layouts, 0, sizeof(out_builder->layouts));364for (uint32_t i = 0; i < mod_props.drmFormatModifierPlaneCount; i++) {365out_builder->layouts[i].offset = buf_props.offset[i];366out_builder->layouts[i].rowPitch = buf_props.stride[i];367}368out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){369.sType =370VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,371.pNext = create_info->pNext,372.drmFormatModifier = buf_props.modifier,373.drmFormatModifierPlaneCount = mod_props.drmFormatModifierPlaneCount,374.pPlaneLayouts = out_builder->layouts,375};376out_builder->external = (VkExternalMemoryImageCreateInfo){377.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,378.pNext = &out_builder->modifier,379.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,380};381out_builder->create = *create_info;382out_builder->create.pNext = &out_builder->external;383out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;384385return VK_SUCCESS;386}387388VkResult389vn_android_image_from_anb(struct vn_device *dev,390const VkImageCreateInfo *create_info,391const VkNativeBufferANDROID *anb_info,392const VkAllocationCallbacks *alloc,393struct vn_image **out_img)394{395/* If anb_info->handle points to a classic resouce created from396* virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the397* guest shadow storage other than the host gpu storage.398*399* We also need to pass the correct stride to vn_CreateImage, which will be400* done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require401* VK_EXT_image_drm_format_modifier support in the host driver. The struct402* needs host storage info which can be queried from cros gralloc.403*/404VkResult result = VK_SUCCESS;405VkDevice device = vn_device_to_handle(dev);406VkDeviceMemory memory = VK_NULL_HANDLE;407VkImage image = VK_NULL_HANDLE;408struct vn_image *img = NULL;409uint64_t alloc_size = 0;410uint32_t mem_type_bits = 0;411int dma_buf_fd = -1;412int dup_fd = -1;413struct vn_android_image_builder builder;414415result = vn_android_get_dma_buf_from_native_handle(anb_info->handle,416&dma_buf_fd);417if (result != VK_SUCCESS)418goto fail;419420result = vn_android_get_image_builder(dev, create_info, anb_info->handle,421alloc, &builder);422if (result != VK_SUCCESS)423goto fail;424425/* encoder will strip the Android specific pNext structs */426result = vn_image_create(dev, &builder.create, alloc, &img);427if (result != VK_SUCCESS) {428if (VN_DEBUG(WSI))429vn_log(dev->instance, "vn_image_create failed");430goto fail;431}432433image = vn_image_to_handle(img);434VkMemoryRequirements mem_req;435vn_GetImageMemoryRequirements(device, image, &mem_req);436if (!mem_req.memoryTypeBits) {437if (VN_DEBUG(WSI))438vn_log(dev->instance, "mem_req.memoryTypeBits cannot be zero");439result = VK_ERROR_INVALID_EXTERNAL_HANDLE;440goto fail;441}442443result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,444&mem_type_bits);445if (result != VK_SUCCESS)446goto fail;447448if (VN_DEBUG(WSI)) {449vn_log(dev->instance,450"size = img(%" PRIu64 ") fd(%" PRIu64 "), "451"memoryTypeBits = img(0x%X) & fd(0x%X)",452mem_req.size, alloc_size, mem_req.memoryTypeBits, mem_type_bits);453}454455if (alloc_size < mem_req.size) {456if (VN_DEBUG(WSI)) {457vn_log(dev->instance,458"alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",459alloc_size, mem_req.size);460}461result = VK_ERROR_INVALID_EXTERNAL_HANDLE;462goto fail;463}464465mem_type_bits &= mem_req.memoryTypeBits;466if (!mem_type_bits) {467result = VK_ERROR_INVALID_EXTERNAL_HANDLE;468goto fail;469}470471dup_fd = os_dupfd_cloexec(dma_buf_fd);472if (dup_fd < 0) {473result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS474: VK_ERROR_OUT_OF_HOST_MEMORY;475goto fail;476}477478const VkImportMemoryFdInfoKHR import_fd_info = {479.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,480.pNext = NULL,481.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,482.fd = dup_fd,483};484const VkMemoryAllocateInfo memory_info = {485.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,486.pNext = &import_fd_info,487.allocationSize = mem_req.size,488.memoryTypeIndex = ffs(mem_type_bits) - 1,489};490result = vn_AllocateMemory(device, &memory_info, alloc, &memory);491if (result != VK_SUCCESS) {492/* only need to close the dup_fd on import failure */493close(dup_fd);494goto fail;495}496497result = vn_BindImageMemory(device, image, memory, 0);498if (result != VK_SUCCESS)499goto fail;500501img->is_wsi = true;502/* Android WSI image owns the memory */503img->private_memory = memory;504*out_img = img;505506return VK_SUCCESS;507508fail:509if (image != VK_NULL_HANDLE)510vn_DestroyImage(device, image, alloc);511if (memory != VK_NULL_HANDLE)512vn_FreeMemory(device, memory, alloc);513return vn_error(dev->instance, result);514}515516VkResult517vn_AcquireImageANDROID(VkDevice device,518UNUSED VkImage image,519int nativeFenceFd,520VkSemaphore semaphore,521VkFence fence)522{523struct vn_device *dev = vn_device_from_handle(device);524VkResult result = VK_SUCCESS;525526if (dev->instance->experimental.globalFencing == VK_FALSE) {527/* Fallback when VkVenusExperimentalFeatures100000MESA::globalFencing is528* VK_FALSE, out semaphore and fence are filled with already signaled529* payloads, and the native fence fd is waited inside until signaled.530*/531if (nativeFenceFd >= 0) {532int ret = sync_wait(nativeFenceFd, -1);533/* Android loader expects the ICD to always close the fd */534close(nativeFenceFd);535if (ret)536return vn_error(dev->instance, VK_ERROR_SURFACE_LOST_KHR);537}538539if (semaphore != VK_NULL_HANDLE)540vn_semaphore_signal_wsi(dev, vn_semaphore_from_handle(semaphore));541542if (fence != VK_NULL_HANDLE)543vn_fence_signal_wsi(dev, vn_fence_from_handle(fence));544545return VK_SUCCESS;546}547548int semaphore_fd = -1;549int fence_fd = -1;550if (nativeFenceFd >= 0) {551if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) {552semaphore_fd = nativeFenceFd;553fence_fd = os_dupfd_cloexec(nativeFenceFd);554if (fence_fd < 0) {555result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS556: VK_ERROR_OUT_OF_HOST_MEMORY;557close(nativeFenceFd);558return vn_error(dev->instance, result);559}560} else if (semaphore != VK_NULL_HANDLE) {561semaphore_fd = nativeFenceFd;562} else if (fence != VK_NULL_HANDLE) {563fence_fd = nativeFenceFd;564} else {565close(nativeFenceFd);566}567}568569if (semaphore != VK_NULL_HANDLE) {570const VkImportSemaphoreFdInfoKHR info = {571.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,572.pNext = NULL,573.semaphore = semaphore,574.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,575.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,576.fd = semaphore_fd,577};578result = vn_ImportSemaphoreFdKHR(device, &info);579if (result == VK_SUCCESS)580semaphore_fd = -1;581}582583if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) {584const VkImportFenceFdInfoKHR info = {585.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,586.pNext = NULL,587.fence = fence,588.flags = VK_FENCE_IMPORT_TEMPORARY_BIT,589.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,590.fd = fence_fd,591};592result = vn_ImportFenceFdKHR(device, &info);593if (result == VK_SUCCESS)594fence_fd = -1;595}596597if (semaphore_fd >= 0)598close(semaphore_fd);599if (fence_fd >= 0)600close(fence_fd);601602return vn_result(dev->instance, result);603}604605VkResult606vn_QueueSignalReleaseImageANDROID(VkQueue queue,607uint32_t waitSemaphoreCount,608const VkSemaphore *pWaitSemaphores,609VkImage image,610int *pNativeFenceFd)611{612struct vn_queue *que = vn_queue_from_handle(queue);613struct vn_device *dev = que->device;614const VkAllocationCallbacks *alloc = &dev->base.base.alloc;615VkDevice device = vn_device_to_handle(dev);616VkPipelineStageFlags local_stage_masks[8];617VkPipelineStageFlags *stage_masks = local_stage_masks;618VkResult result = VK_SUCCESS;619int fd = -1;620621if (waitSemaphoreCount == 0) {622*pNativeFenceFd = -1;623return VK_SUCCESS;624}625626if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {627stage_masks =628vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount,629VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);630if (!stage_masks)631return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);632}633634for (uint32_t i = 0; i < waitSemaphoreCount; i++)635stage_masks[i] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;636637const VkSubmitInfo submit_info = {638.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,639.pNext = NULL,640.waitSemaphoreCount = waitSemaphoreCount,641.pWaitSemaphores = pWaitSemaphores,642.pWaitDstStageMask = stage_masks,643.commandBufferCount = 0,644.pCommandBuffers = NULL,645.signalSemaphoreCount = 0,646.pSignalSemaphores = NULL,647};648/* XXX When globalFencing is supported, our implementation is not able to649* reset the fence during vn_GetFenceFdKHR currently. Thus to ensure proper650* host driver behavior, we pass VK_NULL_HANDLE here.651*/652result = vn_QueueSubmit(653queue, 1, &submit_info,654dev->instance->experimental.globalFencing == VK_TRUE ? VK_NULL_HANDLE655: que->wait_fence);656657if (stage_masks != local_stage_masks)658vk_free(alloc, stage_masks);659660if (result != VK_SUCCESS)661return vn_error(dev->instance, result);662663if (dev->instance->experimental.globalFencing == VK_TRUE) {664const VkFenceGetFdInfoKHR fd_info = {665.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,666.pNext = NULL,667.fence = que->wait_fence,668.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,669};670result = vn_GetFenceFdKHR(device, &fd_info, &fd);671} else {672result =673vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);674if (result != VK_SUCCESS)675return vn_error(dev->instance, result);676677result = vn_ResetFences(device, 1, &que->wait_fence);678}679680if (result != VK_SUCCESS)681return vn_error(dev->instance, result);682683*pNativeFenceFd = fd;684685return VK_SUCCESS;686}687688static VkResult689vn_android_get_ahb_format_properties(690struct vn_device *dev,691const struct AHardwareBuffer *ahb,692VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)693{694AHardwareBuffer_Desc desc;695VkFormat format;696struct vn_android_gralloc_buffer_properties buf_props;697VkDrmFormatModifierPropertiesEXT mod_props;698699AHardwareBuffer_describe(ahb, &desc);700if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |701AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |702AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {703vn_log(dev->instance,704"AHB usage(%" PRIu64 ") must include at least one GPU bit",705desc.usage);706return VK_ERROR_INVALID_EXTERNAL_HANDLE;707}708709/* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */710if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {711out_props->format = VK_FORMAT_UNDEFINED;712return VK_SUCCESS;713}714715if (!vn_android_get_gralloc_buffer_properties(716AHardwareBuffer_getNativeHandle(ahb), &buf_props))717return VK_ERROR_INVALID_EXTERNAL_HANDLE;718719/* We implement AHB extension support with EXT_image_drm_format_modifier.720* It requires us to have a compatible VkFormat but not DRM formats. So if721* the ahb is not intended for backing a VkBuffer, error out early if the722* format is VK_FORMAT_UNDEFINED.723*/724format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);725if (format == VK_FORMAT_UNDEFINED) {726vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",727buf_props.drm_fourcc, desc.format);728return VK_ERROR_INVALID_EXTERNAL_HANDLE;729}730731VkResult result = vn_android_get_modifier_properties(732dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props);733if (result != VK_SUCCESS)734return result;735736/* The spec requires that formatFeatures must include at least one of737* VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or738* VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.739*/740const VkFormatFeatureFlags format_features =741mod_props.drmFormatModifierTilingFeatures |742VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;743*out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {744.sType = out_props->sType,745.pNext = out_props->pNext,746.format = format,747.externalFormat = buf_props.drm_fourcc,748.formatFeatures = format_features,749.samplerYcbcrConversionComponents = {750.r = VK_COMPONENT_SWIZZLE_IDENTITY,751.g = VK_COMPONENT_SWIZZLE_IDENTITY,752.b = VK_COMPONENT_SWIZZLE_IDENTITY,753.a = VK_COMPONENT_SWIZZLE_IDENTITY,754},755.suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,756.suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,757.suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,758.suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,759};760761return VK_SUCCESS;762}763764VkResult765vn_GetAndroidHardwareBufferPropertiesANDROID(766VkDevice device,767const struct AHardwareBuffer *buffer,768VkAndroidHardwareBufferPropertiesANDROID *pProperties)769{770struct vn_device *dev = vn_device_from_handle(device);771VkResult result = VK_SUCCESS;772int dma_buf_fd = -1;773uint64_t alloc_size = 0;774uint32_t mem_type_bits = 0;775776VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =777vk_find_struct(pProperties->pNext,778ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);779if (format_props) {780result =781vn_android_get_ahb_format_properties(dev, buffer, format_props);782if (result != VK_SUCCESS)783return vn_error(dev->instance, result);784}785786const native_handle_t *handle = AHardwareBuffer_getNativeHandle(buffer);787result = vn_android_get_dma_buf_from_native_handle(handle, &dma_buf_fd);788if (result != VK_SUCCESS)789return vn_error(dev->instance, result);790791result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,792&mem_type_bits);793if (result != VK_SUCCESS)794return vn_error(dev->instance, result);795796pProperties->allocationSize = alloc_size;797pProperties->memoryTypeBits = mem_type_bits;798799return VK_SUCCESS;800}801802static AHardwareBuffer *803vn_android_ahb_allocate(uint32_t width,804uint32_t height,805uint32_t layers,806uint32_t format,807uint64_t usage)808{809AHardwareBuffer *ahb = NULL;810AHardwareBuffer_Desc desc;811int ret = 0;812813memset(&desc, 0, sizeof(desc));814desc.width = width;815desc.height = height;816desc.layers = layers;817desc.format = format;818desc.usage = usage;819820ret = AHardwareBuffer_allocate(&desc, &ahb);821if (ret) {822/* We just log the error code here for now since the platform falsely823* maps all gralloc allocation failures to oom.824*/825vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",826width, height, layers, format, usage, ret);827return NULL;828}829830return ahb;831}832833bool834vn_android_get_drm_format_modifier_info(835const VkPhysicalDeviceImageFormatInfo2 *format_info,836VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)837{838/* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have839* to allocate an ahb to retrieve the drm format modifier. For the image840* sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.841*/842AHardwareBuffer *ahb = NULL;843uint32_t format = 0;844uint64_t usage = 0;845struct vn_android_gralloc_buffer_properties buf_props;846847assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);848849format = vn_android_ahb_format_from_vk_format(format_info->format);850if (!format)851return false;852853usage = vn_android_get_ahb_usage(format_info->usage, format_info->flags);854ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);855if (!ahb)856return false;857858if (!vn_android_get_gralloc_buffer_properties(859AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {860AHardwareBuffer_release(ahb);861return false;862}863864*out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){865.sType =866VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,867.pNext = NULL,868.drmFormatModifier = buf_props.modifier,869.sharingMode = VK_SHARING_MODE_EXCLUSIVE,870.queueFamilyIndexCount = 0,871.pQueueFamilyIndices = NULL,872};873874AHardwareBuffer_release(ahb);875return true;876}877878VkResult879vn_android_image_from_ahb(struct vn_device *dev,880const VkImageCreateInfo *create_info,881const VkAllocationCallbacks *alloc,882struct vn_image **out_img)883{884const VkExternalFormatANDROID *ext_info =885vk_find_struct_const(create_info->pNext, EXTERNAL_FORMAT_ANDROID);886887VkImageCreateInfo local_info;888if (ext_info && ext_info->externalFormat) {889assert(create_info->format == VK_FORMAT_UNDEFINED);890assert(create_info->imageType == VK_IMAGE_TYPE_2D);891assert(create_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT);892assert(create_info->tiling == VK_IMAGE_TILING_OPTIMAL);893894local_info = *create_info;895local_info.format =896vn_android_drm_format_to_vk_format(ext_info->externalFormat);897create_info = &local_info;898}899900return vn_image_create_deferred(dev, create_info, alloc, out_img);901}902903VkResult904vn_android_device_import_ahb(struct vn_device *dev,905struct vn_device_memory *mem,906const VkMemoryAllocateInfo *alloc_info,907const VkAllocationCallbacks *alloc,908struct AHardwareBuffer *ahb)909{910VkDevice device = vn_device_to_handle(dev);911const VkMemoryDedicatedAllocateInfo *dedicated_info =912vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);913const native_handle_t *handle = NULL;914int dma_buf_fd = -1;915int dup_fd = -1;916uint64_t alloc_size = 0;917uint32_t mem_type_bits = 0;918VkResult result = VK_SUCCESS;919920handle = AHardwareBuffer_getNativeHandle(ahb);921result = vn_android_get_dma_buf_from_native_handle(handle, &dma_buf_fd);922if (result != VK_SUCCESS)923return result;924925result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,926&mem_type_bits);927if (result != VK_SUCCESS)928return result;929930if (((1 << alloc_info->memoryTypeIndex) & mem_type_bits) == 0) {931vn_log(dev->instance, "memoryTypeIndex(%u) mem_type_bits(0x%X)",932alloc_info->memoryTypeIndex, mem_type_bits);933return VK_ERROR_INVALID_EXTERNAL_HANDLE;934}935936/* If ahb is for an image, finish the deferred image creation first */937if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {938struct vn_image *img = vn_image_from_handle(dedicated_info->image);939struct vn_android_image_builder builder;940941result = vn_android_get_image_builder(dev, &img->deferred_info->create,942handle, alloc, &builder);943if (result != VK_SUCCESS)944return result;945946result = vn_image_init_deferred(dev, &builder.create, img);947if (result != VK_SUCCESS)948return result;949950VkMemoryRequirements mem_req;951vn_GetImageMemoryRequirements(device, dedicated_info->image, &mem_req);952if (alloc_size < mem_req.size) {953vn_log(dev->instance,954"alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",955alloc_size, mem_req.size);956return VK_ERROR_INVALID_EXTERNAL_HANDLE;957}958959alloc_size = mem_req.size;960}961962if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {963VkMemoryRequirements mem_req;964vn_GetBufferMemoryRequirements(device, dedicated_info->buffer,965&mem_req);966if (alloc_size < mem_req.size) {967vn_log(dev->instance,968"alloc_size(%" PRIu64 ") mem_req.size(%" PRIu64 ")",969alloc_size, mem_req.size);970return VK_ERROR_INVALID_EXTERNAL_HANDLE;971}972973alloc_size = mem_req.size;974}975976errno = 0;977dup_fd = os_dupfd_cloexec(dma_buf_fd);978if (dup_fd < 0)979return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS980: VK_ERROR_OUT_OF_HOST_MEMORY;981982/* Spec requires AHB export info to be present, so we must strip it. In983* practice, the AHB import path here only needs the main allocation info984* and the dedicated_info.985*/986VkMemoryDedicatedAllocateInfo local_dedicated_info;987/* Override when dedicated_info exists and is not the tail struct. */988if (dedicated_info && dedicated_info->pNext) {989local_dedicated_info = *dedicated_info;990local_dedicated_info.pNext = NULL;991dedicated_info = &local_dedicated_info;992}993const VkMemoryAllocateInfo local_alloc_info = {994.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,995.pNext = dedicated_info,996.allocationSize = alloc_size,997.memoryTypeIndex = alloc_info->memoryTypeIndex,998};999result =1000vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info, dup_fd);1001if (result != VK_SUCCESS) {1002close(dup_fd);1003return result;1004}10051006AHardwareBuffer_acquire(ahb);1007mem->ahb = ahb;10081009return VK_SUCCESS;1010}10111012VkResult1013vn_android_device_allocate_ahb(struct vn_device *dev,1014struct vn_device_memory *mem,1015const VkMemoryAllocateInfo *alloc_info,1016const VkAllocationCallbacks *alloc)1017{1018const VkMemoryDedicatedAllocateInfo *dedicated_info =1019vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);1020uint32_t width = 0;1021uint32_t height = 1;1022uint32_t layers = 1;1023uint32_t format = 0;1024uint64_t usage = 0;1025struct AHardwareBuffer *ahb = NULL;10261027if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {1028const VkImageCreateInfo *image_info =1029&vn_image_from_handle(dedicated_info->image)->deferred_info->create;1030assert(image_info);1031width = image_info->extent.width;1032height = image_info->extent.height;1033layers = image_info->arrayLayers;1034format = vn_android_ahb_format_from_vk_format(image_info->format);1035usage = vn_android_get_ahb_usage(image_info->usage, image_info->flags);1036} else {1037const VkPhysicalDeviceMemoryProperties *mem_props =1038&dev->physical_device->memory_properties.memoryProperties;10391040assert(alloc_info->memoryTypeIndex < mem_props->memoryTypeCount);10411042width = alloc_info->allocationSize;1043format = AHARDWAREBUFFER_FORMAT_BLOB;1044usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;1045if (mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags &1046VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {1047usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |1048AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;1049}1050}10511052ahb = vn_android_ahb_allocate(width, height, layers, format, usage);1053if (!ahb)1054return VK_ERROR_OUT_OF_HOST_MEMORY;10551056VkResult result =1057vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb);10581059/* ahb alloc has already acquired a ref and import will acquire another,1060* must release one here to avoid leak.1061*/1062AHardwareBuffer_release(ahb);10631064return result;1065}10661067void1068vn_android_release_ahb(struct AHardwareBuffer *ahb)1069{1070AHardwareBuffer_release(ahb);1071}10721073VkResult1074vn_GetMemoryAndroidHardwareBufferANDROID(1075VkDevice device,1076const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,1077struct AHardwareBuffer **pBuffer)1078{1079struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory);10801081AHardwareBuffer_acquire(mem->ahb);1082*pBuffer = mem->ahb;10831084return VK_SUCCESS;1085}10861087struct vn_android_buffer_create_info {1088VkBufferCreateInfo create;1089VkExternalMemoryBufferCreateInfo external;1090VkBufferOpaqueCaptureAddressCreateInfo address;1091};10921093static const VkBufferCreateInfo *1094vn_android_fix_buffer_create_info(1095const VkBufferCreateInfo *create_info,1096struct vn_android_buffer_create_info *local_info)1097{1098local_info->create = *create_info;1099VkBaseOutStructure *dst = (void *)&local_info->create;11001101vk_foreach_struct_const(src, create_info->pNext) {1102void *pnext = NULL;1103switch (src->sType) {1104case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO:1105memcpy(&local_info->external, src, sizeof(local_info->external));1106local_info->external.handleTypes =1107VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;1108pnext = &local_info->external;1109break;1110case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO:1111memcpy(&local_info->address, src, sizeof(local_info->address));1112pnext = &local_info->address;1113break;1114default:1115break;1116}11171118if (pnext) {1119dst->pNext = pnext;1120dst = pnext;1121}1122}11231124dst->pNext = NULL;11251126return &local_info->create;1127}11281129VkResult1130vn_android_init_ahb_buffer_memory_type_bits(struct vn_device *dev)1131{1132const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;1133/* ensure dma_buf_memory_type_bits covers host visible usage */1134const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |1135AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |1136AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;1137AHardwareBuffer *ahb = NULL;1138int dma_buf_fd = -1;1139uint64_t alloc_size = 0;1140uint32_t mem_type_bits = 0;1141VkResult result;11421143ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);1144if (!ahb)1145return VK_ERROR_OUT_OF_HOST_MEMORY;11461147result = vn_android_get_dma_buf_from_native_handle(1148AHardwareBuffer_getNativeHandle(ahb), &dma_buf_fd);1149if (result != VK_SUCCESS) {1150AHardwareBuffer_release(ahb);1151return result;1152}11531154result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,1155&mem_type_bits);11561157AHardwareBuffer_release(ahb);11581159if (result != VK_SUCCESS)1160return result;11611162dev->ahb_buffer_memory_type_bits = mem_type_bits;11631164return VK_SUCCESS;1165}11661167VkResult1168vn_android_buffer_from_ahb(struct vn_device *dev,1169const VkBufferCreateInfo *create_info,1170const VkAllocationCallbacks *alloc,1171struct vn_buffer **out_buf)1172{1173struct vn_android_buffer_create_info local_info;1174VkResult result;11751176create_info = vn_android_fix_buffer_create_info(create_info, &local_info);1177result = vn_buffer_create(dev, create_info, alloc, out_buf);1178if (result != VK_SUCCESS)1179return result;11801181/* AHB backed buffer layers on top of dma_buf, so here we must comine the1182* queried type bits from both buffer memory requirement and dma_buf fd1183* properties.1184*/1185(*out_buf)->memory_requirements.memoryRequirements.memoryTypeBits &=1186dev->ahb_buffer_memory_type_bits;11871188assert((*out_buf)->memory_requirements.memoryRequirements.memoryTypeBits);11891190return VK_SUCCESS;1191}119211931194