1/* 2 * Copyright 2021 Google LLC 3 * SPDX-License-Identifier: MIT 4 * 5 * based in part on anv and radv which are: 6 * Copyright © 2015 Intel Corporation 7 * Copyright © 2016 Red Hat 8 * Copyright © 2016 Bas Nieuwenhuizen 9 */ 10 11#include "vn_android.h" 12 13#include <dlfcn.h> 14#include <hardware/gralloc.h> 15#include <hardware/hwvulkan.h> 16#include <vndk/hardware_buffer.h> 17#include <vulkan/vk_icd.h> 18 19#include "drm-uapi/drm_fourcc.h" 20#include "util/libsync.h" 21#include "util/os_file.h" 22 23#include "vn_buffer.h" 24#include "vn_device.h" 25#include "vn_device_memory.h" 26#include "vn_image.h" 27#include "vn_instance.h" 28#include "vn_physical_device.h" 29#include "vn_queue.h" 30 31/* perform options supported by CrOS Gralloc */ 32#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4 33#define CROS_GRALLOC_DRM_GET_USAGE 5 34#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1 35 36struct vn_android_gralloc { 37 const gralloc_module_t *module; 38 uint32_t front_rendering_usage; 39}; 40 41static struct vn_android_gralloc _vn_android_gralloc; 42 43static int 44vn_android_gralloc_init() 45{ 46 static const char CROS_GRALLOC_MODULE_NAME[] = "CrOS Gralloc"; 47 const gralloc_module_t *gralloc = NULL; 48 uint32_t front_rendering_usage = 0; 49 int ret; 50 51 /* get gralloc module for gralloc buffer info query */ 52 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 53 (const hw_module_t **)&gralloc); 54 if (ret) { 55 vn_log(NULL, "failed to open gralloc module(ret=%d)", ret); 56 return ret; 57 } 58 59 if (strcmp(gralloc->common.name, CROS_GRALLOC_MODULE_NAME) != 0) { 60 dlclose(gralloc->common.dso); 61 vn_log(NULL, "unexpected gralloc (name: %s)", gralloc->common.name); 62 return -1; 63 } 64 65 if (!gralloc->perform) { 66 dlclose(gralloc->common.dso); 67 vn_log(NULL, "missing required gralloc helper: perform"); 68 return -1; 69 } 70 71 if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_USAGE, 72 CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT, 73 &front_rendering_usage) == 0) { 74 assert(front_rendering_usage); 75 _vn_android_gralloc.front_rendering_usage = front_rendering_usage; 76 } 77 78 _vn_android_gralloc.module = gralloc; 79 80 return 0; 81} 82 83static inline void 84vn_android_gralloc_fini() 85{ 86 dlclose(_vn_android_gralloc.module->common.dso); 87} 88 89uint32_t 90vn_android_gralloc_get_shared_present_usage() 91{ 92 return _vn_android_gralloc.front_rendering_usage; 93} 94 95struct cros_gralloc0_buffer_info { 96 uint32_t drm_fourcc; 97 int num_fds; /* ignored */ 98 int fds[4]; /* ignored */ 99 uint64_t modifier; 100 uint32_t offset[4]; 101 uint32_t stride[4]; 102}; 103 104struct vn_android_gralloc_buffer_properties { 105 uint32_t drm_fourcc; 106 uint64_t modifier; 107 108 /* plane order matches VkImageDrmFormatModifierExplicitCreateInfoEXT */ 109 uint32_t offset[4]; 110 uint32_t stride[4]; 111}; 112 113static bool 114vn_android_gralloc_get_buffer_properties( 115 buffer_handle_t handle, 116 struct vn_android_gralloc_buffer_properties *out_props) 117{ 118 const gralloc_module_t *gralloc = _vn_android_gralloc.module; 119 struct cros_gralloc0_buffer_info info; 120 if (gralloc->perform(gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO, handle, 121 &info) != 0) { 122 vn_log(NULL, "CROS_GRALLOC_DRM_GET_BUFFER_INFO failed"); 123 return false; 124 } 125 126 if (info.modifier == DRM_FORMAT_MOD_INVALID) { 127 vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID"); 128 return false; 129 } 130 131 out_props->drm_fourcc = info.drm_fourcc; 132 for (uint32_t i = 0; i < 4; i++) { 133 out_props->stride[i] = info.stride[i]; 134 out_props->offset[i] = info.offset[i]; 135 } 136 137 /* YVU420 has a chroma order of CrCb. So we must swap the planes for CrCb 138 * to align with VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM. This is to serve 139 * VkImageDrmFormatModifierExplicitCreateInfoEXT explicit plane layouts. 140 */ 141 if (info.drm_fourcc == DRM_FORMAT_YVU420) { 142 out_props->stride[1] = info.stride[2]; 143 out_props->offset[1] = info.offset[2]; 144 out_props->stride[2] = info.stride[1]; 145 out_props->offset[2] = info.offset[1]; 146 } 147 148 out_props->modifier = info.modifier; 149 150 return true; 151} 152 153static int 154vn_android_gralloc_get_dma_buf_fd(const native_handle_t *handle) 155{ 156 /* There can be multiple fds wrapped inside a native_handle_t, but we 157 * expect the 1st one pointing to the dma_buf. For multi-planar format, 158 * there should only exist one undelying dma_buf. The other fd(s) could be 159 * dups to the same dma_buf or point to the shared memory used to store 160 * gralloc buffer metadata. 161 */ 162 assert(handle); 163 164 if (handle->numFds < 1) { 165 vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds); 166 return -1; 167 } 168 169 if (handle->data[0] < 0) { 170 vn_log(NULL, "handle->data[0] < 0"); 171 return -1; 172 } 173 174 return handle->data[0]; 175} 176 177static int 178vn_hal_open(const struct hw_module_t *mod, 179 const char *id, 180 struct hw_device_t **dev); 181 182static void UNUSED 183static_asserts(void) 184{ 185 STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC); 186} 187 188PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = { 189 .common = { 190 .tag = HARDWARE_MODULE_TAG, 191 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1, 192 .hal_api_version = HARDWARE_HAL_API_VERSION, 193 .id = HWVULKAN_HARDWARE_MODULE_ID, 194 .name = "Venus Vulkan HAL", 195 .author = "Google LLC", 196 .methods = &(hw_module_methods_t) { 197 .open = vn_hal_open, 198 }, 199 }, 200}; 201 202static int 203vn_hal_close(UNUSED struct hw_device_t *dev) 204{ 205 vn_android_gralloc_fini(); 206 return 0; 207} 208 209static hwvulkan_device_t vn_hal_dev = { 210 .common = { 211 .tag = HARDWARE_DEVICE_TAG, 212 .version = HWVULKAN_DEVICE_API_VERSION_0_1, 213 .module = &HAL_MODULE_INFO_SYM.common, 214 .close = vn_hal_close, 215 }, 216 .EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties, 217 .CreateInstance = vn_CreateInstance, 218 .GetInstanceProcAddr = vn_GetInstanceProcAddr, 219}; 220 221static int 222vn_hal_open(const struct hw_module_t *mod, 223 const char *id, 224 struct hw_device_t **dev) 225{ 226 int ret; 227 228 assert(mod == &HAL_MODULE_INFO_SYM.common); 229 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0); 230 231 ret = vn_android_gralloc_init(); 232 if (ret) 233 return ret; 234 235 *dev = &vn_hal_dev.common; 236 237 return 0; 238} 239 240static uint32_t 241vn_android_ahb_format_from_vk_format(VkFormat format) 242{ 243 /* Only non-external AHB compatible formats are expected at: 244 * - image format query 245 * - memory export allocation 246 */ 247 switch (format) { 248 case VK_FORMAT_R8G8B8A8_UNORM: 249 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 250 case VK_FORMAT_R8G8B8_UNORM: 251 return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM; 252 case VK_FORMAT_R5G6B5_UNORM_PACK16: 253 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; 254 case VK_FORMAT_R16G16B16A16_SFLOAT: 255 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT; 256 case VK_FORMAT_A2B10G10R10_UNORM_PACK32: 257 return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; 258 default: 259 return 0; 260 } 261} 262 263const VkFormat * 264vn_android_format_to_view_formats(VkFormat format, uint32_t *out_count) 265{ 266 /* For AHB image prop query and creation, venus overrides the tiling to 267 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, which requires to chain 268 * VkImageFormatListCreateInfo struct in the corresponding pNext when the 269 * VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is set. Those AHB images are assumed 270 * to be mutable no more than sRGB-ness, and the implementations can fail 271 * whenever going beyond. 272 * 273 * This helper provides the view formats that have sRGB variants for the 274 * image format that venus supports. 275 */ 276 static const VkFormat view_formats_r8g8b8a8[] = { 277 VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB 278 }; 279 static const VkFormat view_formats_r8g8b8[] = { VK_FORMAT_R8G8B8_UNORM, 280 VK_FORMAT_R8G8B8_SRGB }; 281 282 switch (format) { 283 case VK_FORMAT_R8G8B8A8_UNORM: 284 *out_count = ARRAY_SIZE(view_formats_r8g8b8a8); 285 return view_formats_r8g8b8a8; 286 break; 287 case VK_FORMAT_R8G8B8_UNORM: 288 *out_count = ARRAY_SIZE(view_formats_r8g8b8); 289 return view_formats_r8g8b8; 290 break; 291 default: 292 /* let the caller handle the fallback case */ 293 *out_count = 0; 294 return NULL; 295 } 296} 297 298VkFormat 299vn_android_drm_format_to_vk_format(uint32_t format) 300{ 301 switch (format) { 302 case DRM_FORMAT_ABGR8888: 303 case DRM_FORMAT_XBGR8888: 304 return VK_FORMAT_R8G8B8A8_UNORM; 305 case DRM_FORMAT_BGR888: 306 return VK_FORMAT_R8G8B8_UNORM; 307 case DRM_FORMAT_RGB565: 308 return VK_FORMAT_R5G6B5_UNORM_PACK16; 309 case DRM_FORMAT_ABGR16161616F: 310 return VK_FORMAT_R16G16B16A16_SFLOAT; 311 case DRM_FORMAT_ABGR2101010: 312 return VK_FORMAT_A2B10G10R10_UNORM_PACK32; 313 case DRM_FORMAT_YVU420: 314 return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; 315 case DRM_FORMAT_NV12: 316 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; 317 default: 318 return VK_FORMAT_UNDEFINED; 319 } 320} 321 322static bool 323vn_android_drm_format_is_yuv(uint32_t format) 324{ 325 assert(vn_android_drm_format_to_vk_format(format) != VK_FORMAT_UNDEFINED); 326 327 switch (format) { 328 case DRM_FORMAT_YVU420: 329 case DRM_FORMAT_NV12: 330 return true; 331 default: 332 return false; 333 } 334} 335 336uint64_t 337vn_android_get_ahb_usage(const VkImageUsageFlags usage, 338 const VkImageCreateFlags flags) 339{ 340 uint64_t ahb_usage = 0; 341 if (usage & 342 (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) 343 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; 344 345 if (usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 346 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) 347 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; 348 349 if (flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) 350 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; 351 352 if (flags & VK_IMAGE_CREATE_PROTECTED_BIT) 353 ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; 354 355 /* must include at least one GPU usage flag */ 356 if (ahb_usage == 0) 357 ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; 358 359 return ahb_usage; 360} 361 362VkResult 363vn_GetSwapchainGrallocUsage2ANDROID( 364 VkDevice device, 365 VkFormat format, 366 VkImageUsageFlags imageUsage, 367 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, 368 uint64_t *grallocConsumerUsage, 369 uint64_t *grallocProducerUsage) 370{ 371 struct vn_device *dev = vn_device_from_handle(device); 372 373 if (VN_DEBUG(WSI)) { 374 vn_log(dev->instance, 375 "format=%d, imageUsage=0x%x, swapchainImageUsage=0x%x", format, 376 imageUsage, swapchainImageUsage); 377 } 378 379 *grallocConsumerUsage = 0; 380 *grallocProducerUsage = 0; 381 if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT | 382 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) 383 *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; 384 385 if (imageUsage & 386 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | 387 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) 388 *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; 389 390 if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID) 391 *grallocProducerUsage |= vn_android_gralloc_get_shared_present_usage(); 392 393 return VK_SUCCESS; 394} 395 396static VkResult 397vn_android_get_modifier_properties(struct vn_device *dev, 398 VkFormat format, 399 uint64_t modifier, 400 const VkAllocationCallbacks *alloc, 401 VkDrmFormatModifierPropertiesEXT *out_props) 402{ 403 VkPhysicalDevice physical_device = 404 vn_physical_device_to_handle(dev->physical_device); 405 VkDrmFormatModifierPropertiesListEXT mod_prop_list = { 406 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, 407 .pNext = NULL, 408 .drmFormatModifierCount = 0, 409 .pDrmFormatModifierProperties = NULL, 410 }; 411 VkFormatProperties2 format_prop = { 412 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, 413 .pNext = &mod_prop_list, 414 }; 415 VkDrmFormatModifierPropertiesEXT *mod_props = NULL; 416 bool modifier_found = false; 417 418 vn_GetPhysicalDeviceFormatProperties2(physical_device, format, 419 &format_prop); 420 421 if (!mod_prop_list.drmFormatModifierCount) { 422 vn_log(dev->instance, "No compatible modifier for VkFormat(%u)", 423 format); 424 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 425 } 426 427 mod_props = vk_zalloc( 428 alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount, 429 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 430 if (!mod_props) 431 return VK_ERROR_OUT_OF_HOST_MEMORY; 432 433 mod_prop_list.pDrmFormatModifierProperties = mod_props; 434 vn_GetPhysicalDeviceFormatProperties2(physical_device, format, 435 &format_prop); 436 437 for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) { 438 if (mod_props[i].drmFormatModifier == modifier) { 439 *out_props = mod_props[i]; 440 modifier_found = true; 441 break; 442 } 443 } 444 445 vk_free(alloc, mod_props); 446 447 if (!modifier_found) { 448 vn_log(dev->instance, 449 "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)", 450 modifier, format); 451 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 452 } 453 454 return VK_SUCCESS; 455} 456 457struct vn_android_image_builder { 458 VkImageCreateInfo create; 459 VkSubresourceLayout layouts[4]; 460 VkImageDrmFormatModifierExplicitCreateInfoEXT modifier; 461 VkExternalMemoryImageCreateInfo external; 462 VkImageFormatListCreateInfo list; 463}; 464 465static VkResult 466vn_android_get_image_builder(struct vn_device *dev, 467 const VkImageCreateInfo *create_info, 468 const native_handle_t *handle, 469 const VkAllocationCallbacks *alloc, 470 struct vn_android_image_builder *out_builder) 471{ 472 VkResult result = VK_SUCCESS; 473 struct vn_android_gralloc_buffer_properties buf_props; 474 VkDrmFormatModifierPropertiesEXT mod_props; 475 uint32_t vcount = 0; 476 const VkFormat *vformats = NULL; 477 478 /* Android image builder is only used by ANB or AHB. For ANB, Android 479 * Vulkan loader will never pass the below structs. For AHB, struct 480 * vn_image_create_deferred_info will never carry below either. 481 */ 482 assert(!vk_find_struct_const( 483 create_info->pNext, 484 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT)); 485 assert(!vk_find_struct_const(create_info->pNext, 486 EXTERNAL_MEMORY_IMAGE_CREATE_INFO)); 487 488 if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props)) 489 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 490 491 result = vn_android_get_modifier_properties( 492 dev, create_info->format, buf_props.modifier, alloc, &mod_props); 493 if (result != VK_SUCCESS) 494 return result; 495 496 /* fill VkImageCreateInfo */ 497 memset(out_builder, 0, sizeof(*out_builder)); 498 out_builder->create = *create_info; 499 out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; 500 501 /* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */ 502 for (uint32_t i = 0; i < mod_props.drmFormatModifierPlaneCount; i++) { 503 out_builder->layouts[i].offset = buf_props.offset[i]; 504 out_builder->layouts[i].rowPitch = buf_props.stride[i]; 505 } 506 out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){ 507 .sType = 508 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT, 509 .pNext = out_builder->create.pNext, 510 .drmFormatModifier = buf_props.modifier, 511 .drmFormatModifierPlaneCount = mod_props.drmFormatModifierPlaneCount, 512 .pPlaneLayouts = out_builder->layouts, 513 }; 514 out_builder->create.pNext = &out_builder->modifier; 515 516 /* fill VkExternalMemoryImageCreateInfo */ 517 out_builder->external = (VkExternalMemoryImageCreateInfo){ 518 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 519 .pNext = out_builder->create.pNext, 520 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 521 }; 522 out_builder->create.pNext = &out_builder->external; 523 524 /* fill VkImageFormatListCreateInfo if needed 525 * 526 * vn_image::deferred_info only stores VkImageFormatListCreateInfo with a 527 * non-zero viewFormatCount, and that stored struct will be respected. 528 */ 529 if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) && 530 !vk_find_struct_const(create_info->pNext, 531 IMAGE_FORMAT_LIST_CREATE_INFO)) { 532 /* 12.3. Images 533 * 534 * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags 535 * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain 536 * must include a VkImageFormatListCreateInfo structure with non-zero 537 * viewFormatCount. 538 */ 539 vformats = 540 vn_android_format_to_view_formats(create_info->format, &vcount); 541 if (!vformats) { 542 /* image builder struct persists through the image creation call */ 543 vformats = &out_builder->create.format; 544 vcount = 1; 545 } 546 out_builder->list = (VkImageFormatListCreateInfo){ 547 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO, 548 .pNext = out_builder->create.pNext, 549 .viewFormatCount = vcount, 550 .pViewFormats = vformats, 551 }; 552 out_builder->create.pNext = &out_builder->list; 553 } 554 555 return VK_SUCCESS; 556} 557 558VkResult 559vn_android_image_from_anb(struct vn_device *dev, 560 const VkImageCreateInfo *create_info, 561 const VkNativeBufferANDROID *anb_info, 562 const VkAllocationCallbacks *alloc, 563 struct vn_image **out_img) 564{ 565 /* If anb_info->handle points to a classic resouce created from 566 * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the 567 * guest shadow storage other than the host gpu storage. 568 * 569 * We also need to pass the correct stride to vn_CreateImage, which will be 570 * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require 571 * VK_EXT_image_drm_format_modifier support in the host driver. The struct 572 * needs host storage info which can be queried from cros gralloc. 573 */ 574 VkResult result = VK_SUCCESS; 575 VkDevice device = vn_device_to_handle(dev); 576 VkDeviceMemory memory = VK_NULL_HANDLE; 577 VkImage image = VK_NULL_HANDLE; 578 struct vn_image *img = NULL; 579 uint64_t alloc_size = 0; 580 uint32_t mem_type_bits = 0; 581 int dma_buf_fd = -1; 582 int dup_fd = -1; 583 VkImageCreateInfo local_create_info; 584 struct vn_android_image_builder builder; 585 586 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle); 587 if (dma_buf_fd < 0) { 588 result = VK_ERROR_INVALID_EXTERNAL_HANDLE; 589 goto fail; 590 } 591 592 assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)); 593 assert(!vk_find_struct_const(create_info->pNext, 594 IMAGE_FORMAT_LIST_CREATE_INFO)); 595 assert(!vk_find_struct_const(create_info->pNext, 596 IMAGE_STENCIL_USAGE_CREATE_INFO)); 597 598 /* strip VkNativeBufferANDROID and VkSwapchainImageCreateInfoANDROID */ 599 local_create_info = *create_info; 600 local_create_info.pNext = NULL; 601 result = vn_android_get_image_builder(dev, &local_create_info, 602 anb_info->handle, alloc, &builder); 603 if (result != VK_SUCCESS) 604 goto fail; 605 606 /* encoder will strip the Android specific pNext structs */ 607 result = vn_image_create(dev, &builder.create, alloc, &img); 608 if (result != VK_SUCCESS) { 609 if (VN_DEBUG(WSI)) 610 vn_log(dev->instance, "vn_image_create failed"); 611 goto fail; 612 } 613 614 image = vn_image_to_handle(img); 615 616 const VkMemoryRequirements *mem_req = 617 &img->requirements[0].memory.memoryRequirements; 618 if (!mem_req->memoryTypeBits) { 619 if (VN_DEBUG(WSI)) 620 vn_log(dev->instance, "mem_req->memoryTypeBits cannot be zero"); 621 result = VK_ERROR_INVALID_EXTERNAL_HANDLE; 622 goto fail; 623 } 624 625 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size, 626 &mem_type_bits); 627 if (result != VK_SUCCESS) 628 goto fail; 629 630 if (VN_DEBUG(WSI)) { 631 vn_log(dev->instance, 632 "size = img(%" PRIu64 ") fd(%" PRIu64 "), " 633 "memoryTypeBits = img(0x%X) & fd(0x%X)", 634 mem_req->size, alloc_size, mem_req->memoryTypeBits, 635 mem_type_bits); 636 } 637 638 if (alloc_size < mem_req->size) { 639 if (VN_DEBUG(WSI)) { 640 vn_log(dev->instance, 641 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")", 642 alloc_size, mem_req->size); 643 } 644 result = VK_ERROR_INVALID_EXTERNAL_HANDLE; 645 goto fail; 646 } 647 648 mem_type_bits &= mem_req->memoryTypeBits; 649 if (!mem_type_bits) { 650 result = VK_ERROR_INVALID_EXTERNAL_HANDLE; 651 goto fail; 652 } 653 654 dup_fd = os_dupfd_cloexec(dma_buf_fd); 655 if (dup_fd < 0) { 656 result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS 657 : VK_ERROR_OUT_OF_HOST_MEMORY; 658 goto fail; 659 } 660 661 const VkImportMemoryFdInfoKHR import_fd_info = { 662 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 663 .pNext = NULL, 664 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 665 .fd = dup_fd, 666 }; 667 const VkMemoryAllocateInfo memory_info = { 668 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 669 .pNext = &import_fd_info, 670 .allocationSize = mem_req->size, 671 .memoryTypeIndex = ffs(mem_type_bits) - 1, 672 }; 673 result = vn_AllocateMemory(device, &memory_info, alloc, &memory); 674 if (result != VK_SUCCESS) { 675 /* only need to close the dup_fd on import failure */ 676 close(dup_fd); 677 goto fail; 678 } 679 680 const VkBindImageMemoryInfo bind_info = { 681 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, 682 .pNext = NULL, 683 .image = image, 684 .memory = memory, 685 .memoryOffset = 0, 686 }; 687 result = vn_BindImageMemory2(device, 1, &bind_info); 688 if (result != VK_SUCCESS) 689 goto fail; 690 691 img->wsi.is_wsi = true; 692 img->wsi.tiling_override = builder.create.tiling; 693 img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier; 694 /* Android WSI image owns the memory */ 695 img->wsi.memory = vn_device_memory_from_handle(memory); 696 img->wsi.memory_owned = true; 697 *out_img = img; 698 699 return VK_SUCCESS; 700 701fail: 702 if (image != VK_NULL_HANDLE) 703 vn_DestroyImage(device, image, alloc); 704 if (memory != VK_NULL_HANDLE) 705 vn_FreeMemory(device, memory, alloc); 706 return vn_error(dev->instance, result); 707} 708 709VkResult 710vn_AcquireImageANDROID(VkDevice device, 711 UNUSED VkImage image, 712 int nativeFenceFd, 713 VkSemaphore semaphore, 714 VkFence fence) 715{ 716 VN_TRACE_FUNC(); 717 struct vn_device *dev = vn_device_from_handle(device); 718 VkResult result = VK_SUCCESS; 719 720 if (dev->instance->experimental.globalFencing == VK_FALSE) { 721 /* Fallback when VkVenusExperimentalFeatures100000MESA::globalFencing is 722 * VK_FALSE, out semaphore and fence are filled with already signaled 723 * payloads, and the native fence fd is waited inside until signaled. 724 */ 725 if (nativeFenceFd >= 0) { 726 int ret = sync_wait(nativeFenceFd, -1); 727 /* Android loader expects the ICD to always close the fd */ 728 close(nativeFenceFd); 729 if (ret) 730 return vn_error(dev->instance, VK_ERROR_SURFACE_LOST_KHR); 731 } 732 733 if (semaphore != VK_NULL_HANDLE) 734 vn_semaphore_signal_wsi(dev, vn_semaphore_from_handle(semaphore)); 735 736 if (fence != VK_NULL_HANDLE) 737 vn_fence_signal_wsi(dev, vn_fence_from_handle(fence)); 738 739 return VK_SUCCESS; 740 } 741 742 int semaphore_fd = -1; 743 int fence_fd = -1; 744 if (nativeFenceFd >= 0) { 745 if (semaphore != VK_NULL_HANDLE && fence != VK_NULL_HANDLE) { 746 semaphore_fd = nativeFenceFd; 747 fence_fd = os_dupfd_cloexec(nativeFenceFd); 748 if (fence_fd < 0) { 749 result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS 750 : VK_ERROR_OUT_OF_HOST_MEMORY; 751 close(nativeFenceFd); 752 return vn_error(dev->instance, result); 753 } 754 } else if (semaphore != VK_NULL_HANDLE) { 755 semaphore_fd = nativeFenceFd; 756 } else if (fence != VK_NULL_HANDLE) { 757 fence_fd = nativeFenceFd; 758 } else { 759 close(nativeFenceFd); 760 } 761 } 762 763 if (semaphore != VK_NULL_HANDLE) { 764 const VkImportSemaphoreFdInfoKHR info = { 765 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, 766 .pNext = NULL, 767 .semaphore = semaphore, 768 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, 769 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 770 .fd = semaphore_fd, 771 }; 772 result = vn_ImportSemaphoreFdKHR(device, &info); 773 if (result == VK_SUCCESS) 774 semaphore_fd = -1; 775 } 776 777 if (result == VK_SUCCESS && fence != VK_NULL_HANDLE) { 778 const VkImportFenceFdInfoKHR info = { 779 .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, 780 .pNext = NULL, 781 .fence = fence, 782 .flags = VK_FENCE_IMPORT_TEMPORARY_BIT, 783 .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, 784 .fd = fence_fd, 785 }; 786 result = vn_ImportFenceFdKHR(device, &info); 787 if (result == VK_SUCCESS) 788 fence_fd = -1; 789 } 790 791 if (semaphore_fd >= 0) 792 close(semaphore_fd); 793 if (fence_fd >= 0) 794 close(fence_fd); 795 796 return vn_result(dev->instance, result); 797} 798 799VkResult 800vn_QueueSignalReleaseImageANDROID(VkQueue queue, 801 uint32_t waitSemaphoreCount, 802 const VkSemaphore *pWaitSemaphores, 803 VkImage image, 804 int *pNativeFenceFd) 805{ 806 VN_TRACE_FUNC(); 807 struct vn_queue *que = vn_queue_from_handle(queue); 808 struct vn_device *dev = que->device; 809 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 810 VkDevice device = vn_device_to_handle(dev); 811 VkPipelineStageFlags local_stage_masks[8]; 812 VkPipelineStageFlags *stage_masks = local_stage_masks; 813 VkResult result = VK_SUCCESS; 814 int fd = -1; 815 816 if (waitSemaphoreCount == 0) { 817 *pNativeFenceFd = -1; 818 return VK_SUCCESS; 819 } 820 821 if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) { 822 stage_masks = 823 vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount, 824 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 825 if (!stage_masks) 826 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 827 } 828 829 for (uint32_t i = 0; i < waitSemaphoreCount; i++) 830 stage_masks[i] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 831 832 const VkSubmitInfo submit_info = { 833 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 834 .pNext = NULL, 835 .waitSemaphoreCount = waitSemaphoreCount, 836 .pWaitSemaphores = pWaitSemaphores, 837 .pWaitDstStageMask = stage_masks, 838 .commandBufferCount = 0, 839 .pCommandBuffers = NULL, 840 .signalSemaphoreCount = 0, 841 .pSignalSemaphores = NULL, 842 }; 843 /* XXX When globalFencing is supported, our implementation is not able to 844 * reset the fence during vn_GetFenceFdKHR currently. Thus to ensure proper 845 * host driver behavior, we pass VK_NULL_HANDLE here. 846 */ 847 result = vn_QueueSubmit( 848 queue, 1, &submit_info, 849 dev->instance->experimental.globalFencing == VK_TRUE ? VK_NULL_HANDLE 850 : que->wait_fence); 851 852 if (stage_masks != local_stage_masks) 853 vk_free(alloc, stage_masks); 854 855 if (result != VK_SUCCESS) 856 return vn_error(dev->instance, result); 857 858 if (dev->instance->experimental.globalFencing == VK_TRUE) { 859 /* With globalFencing, the external queue fence was not passed in the 860 * above vn_QueueSubmit to hint it to be synchronous. So we need to wait 861 * for the ring here before vn_GetFenceFdKHR which is pure kernel ops. 862 * Skip ring wait if async queue submit is disabled. 863 */ 864 if (!VN_PERF(NO_ASYNC_QUEUE_SUBMIT)) 865 vn_instance_ring_wait(dev->instance); 866 867 const VkFenceGetFdInfoKHR fd_info = { 868 .sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, 869 .pNext = NULL, 870 .fence = que->wait_fence, 871 .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, 872 }; 873 result = vn_GetFenceFdKHR(device, &fd_info, &fd); 874 } else { 875 result = 876 vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX); 877 if (result != VK_SUCCESS) 878 return vn_error(dev->instance, result); 879 880 result = vn_ResetFences(device, 1, &que->wait_fence); 881 } 882 883 if (result != VK_SUCCESS) 884 return vn_error(dev->instance, result); 885 886 *pNativeFenceFd = fd; 887 888 return VK_SUCCESS; 889} 890 891static VkResult 892vn_android_get_ahb_format_properties( 893 struct vn_device *dev, 894 const struct AHardwareBuffer *ahb, 895 VkAndroidHardwareBufferFormatPropertiesANDROID *out_props) 896{ 897 AHardwareBuffer_Desc desc; 898 VkFormat format; 899 struct vn_android_gralloc_buffer_properties buf_props; 900 VkDrmFormatModifierPropertiesEXT mod_props; 901 902 AHardwareBuffer_describe(ahb, &desc); 903 if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | 904 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER | 905 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) { 906 vn_log(dev->instance, 907 "AHB usage(%" PRIu64 ") must include at least one GPU bit", 908 desc.usage); 909 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 910 } 911 912 /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */ 913 if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) { 914 out_props->format = VK_FORMAT_UNDEFINED; 915 return VK_SUCCESS; 916 } 917 918 if (!vn_android_gralloc_get_buffer_properties( 919 AHardwareBuffer_getNativeHandle(ahb), &buf_props)) 920 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 921 922 /* We implement AHB extension support with EXT_image_drm_format_modifier. 923 * It requires us to have a compatible VkFormat but not DRM formats. So if 924 * the ahb is not intended for backing a VkBuffer, error out early if the 925 * format is VK_FORMAT_UNDEFINED. 926 */ 927 format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc); 928 if (format == VK_FORMAT_UNDEFINED) { 929 vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)", 930 buf_props.drm_fourcc, desc.format); 931 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 932 } 933 934 VkResult result = vn_android_get_modifier_properties( 935 dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props); 936 if (result != VK_SUCCESS) 937 return result; 938 939 /* The spec requires that formatFeatures must include at least one of 940 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or 941 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT. 942 */ 943 const VkFormatFeatureFlags format_features = 944 mod_props.drmFormatModifierTilingFeatures | 945 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT; 946 947 /* 11.2.7. Android Hardware Buffer External Memory 948 * 949 * Implementations may not always be able to determine the color model, 950 * numerical range, or chroma offsets of the image contents, so the values 951 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions. 952 * Applications should treat these values as sensible defaults to use in the 953 * absence of more reliable information obtained through some other means. 954 */ 955 const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc); 956 const VkSamplerYcbcrModelConversion model = 957 is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 958 : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; 959 960 /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from 961 * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar 962 * AHB formats. Venus supports below explicit ones: 963 * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12) 964 * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420) 965 */ 966 if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv) 967 format = VK_FORMAT_UNDEFINED; 968 969 *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) { 970 .sType = out_props->sType, 971 .pNext = out_props->pNext, 972 .format = format, 973 .externalFormat = buf_props.drm_fourcc, 974 .formatFeatures = format_features, 975 .samplerYcbcrConversionComponents = { 976 .r = VK_COMPONENT_SWIZZLE_IDENTITY, 977 .g = VK_COMPONENT_SWIZZLE_IDENTITY, 978 .b = VK_COMPONENT_SWIZZLE_IDENTITY, 979 .a = VK_COMPONENT_SWIZZLE_IDENTITY, 980 }, 981 .suggestedYcbcrModel = model, 982 /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */ 983 .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW, 984 .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT, 985 .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT, 986 }; 987 988 return VK_SUCCESS; 989} 990 991VkResult 992vn_GetAndroidHardwareBufferPropertiesANDROID( 993 VkDevice device, 994 const struct AHardwareBuffer *buffer, 995 VkAndroidHardwareBufferPropertiesANDROID *pProperties) 996{ 997 VN_TRACE_FUNC(); 998 struct vn_device *dev = vn_device_from_handle(device); 999 VkResult result = VK_SUCCESS; 1000 int dma_buf_fd = -1; 1001 uint64_t alloc_size = 0; 1002 uint32_t mem_type_bits = 0; 1003 1004 VkAndroidHardwareBufferFormatPropertiesANDROID *format_props = 1005 vk_find_struct(pProperties->pNext, 1006 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); 1007 if (format_props) { 1008 result = 1009 vn_android_get_ahb_format_properties(dev, buffer, format_props); 1010 if (result != VK_SUCCESS) 1011 return vn_error(dev->instance, result); 1012 } 1013 1014 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd( 1015 AHardwareBuffer_getNativeHandle(buffer)); 1016 if (dma_buf_fd < 0) 1017 return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 1018 1019 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size, 1020 &mem_type_bits); 1021 if (result != VK_SUCCESS) 1022 return vn_error(dev->instance, result); 1023 1024 pProperties->allocationSize = alloc_size; 1025 pProperties->memoryTypeBits = mem_type_bits; 1026 1027 return VK_SUCCESS; 1028} 1029 1030static AHardwareBuffer * 1031vn_android_ahb_allocate(uint32_t width, 1032 uint32_t height, 1033 uint32_t layers, 1034 uint32_t format, 1035 uint64_t usage) 1036{ 1037 AHardwareBuffer *ahb = NULL; 1038 AHardwareBuffer_Desc desc; 1039 int ret = 0; 1040 1041 memset(&desc, 0, sizeof(desc)); 1042 desc.width = width; 1043 desc.height = height; 1044 desc.layers = layers; 1045 desc.format = format; 1046 desc.usage = usage; 1047 1048 ret = AHardwareBuffer_allocate(&desc, &ahb); 1049 if (ret) { 1050 /* We just log the error code here for now since the platform falsely 1051 * maps all gralloc allocation failures to oom. 1052 */ 1053 vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)", 1054 width, height, layers, format, usage, ret); 1055 return NULL; 1056 } 1057 1058 return ahb; 1059} 1060 1061bool 1062vn_android_get_drm_format_modifier_info( 1063 const VkPhysicalDeviceImageFormatInfo2 *format_info, 1064 VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info) 1065{ 1066 /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have 1067 * to allocate an ahb to retrieve the drm format modifier. For the image 1068 * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now. 1069 */ 1070 AHardwareBuffer *ahb = NULL; 1071 uint32_t format = 0; 1072 uint64_t usage = 0; 1073 struct vn_android_gralloc_buffer_properties buf_props; 1074 1075 assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT); 1076 1077 format = vn_android_ahb_format_from_vk_format(format_info->format); 1078 if (!format) 1079 return false; 1080 1081 usage = vn_android_get_ahb_usage(format_info->usage, format_info->flags); 1082 ahb = vn_android_ahb_allocate(16, 16, 1, format, usage); 1083 if (!ahb) 1084 return false; 1085 1086 if (!vn_android_gralloc_get_buffer_properties( 1087 AHardwareBuffer_getNativeHandle(ahb), &buf_props)) { 1088 AHardwareBuffer_release(ahb); 1089 return false; 1090 } 1091 1092 *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){ 1093 .sType = 1094 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, 1095 .pNext = NULL, 1096 .drmFormatModifier = buf_props.modifier, 1097 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 1098 .queueFamilyIndexCount = 0, 1099 .pQueueFamilyIndices = NULL, 1100 }; 1101 1102 AHardwareBuffer_release(ahb); 1103 return true; 1104} 1105 1106VkResult 1107vn_android_image_from_ahb(struct vn_device *dev, 1108 const VkImageCreateInfo *create_info, 1109 const VkAllocationCallbacks *alloc, 1110 struct vn_image **out_img) 1111{ 1112 const VkExternalFormatANDROID *ext_info = 1113 vk_find_struct_const(create_info->pNext, EXTERNAL_FORMAT_ANDROID); 1114 1115 VkImageCreateInfo local_info; 1116 if (ext_info && ext_info->externalFormat) { 1117 assert(create_info->format == VK_FORMAT_UNDEFINED); 1118 assert(create_info->imageType == VK_IMAGE_TYPE_2D); 1119 assert(create_info->usage == VK_IMAGE_USAGE_SAMPLED_BIT); 1120 assert(create_info->tiling == VK_IMAGE_TILING_OPTIMAL); 1121 assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)); 1122 1123 local_info = *create_info; 1124 local_info.format = 1125 vn_android_drm_format_to_vk_format(ext_info->externalFormat); 1126 create_info = &local_info; 1127 } 1128 1129 return vn_image_create_deferred(dev, create_info, alloc, out_img); 1130} 1131 1132VkResult 1133vn_android_device_import_ahb(struct vn_device *dev, 1134 struct vn_device_memory *mem, 1135 const VkMemoryAllocateInfo *alloc_info, 1136 const VkAllocationCallbacks *alloc, 1137 struct AHardwareBuffer *ahb, 1138 bool internal_ahb) 1139{ 1140 const VkMemoryDedicatedAllocateInfo *dedicated_info = 1141 vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); 1142 const native_handle_t *handle = NULL; 1143 int dma_buf_fd = -1; 1144 int dup_fd = -1; 1145 uint64_t alloc_size = 0; 1146 uint32_t mem_type_bits = 0; 1147 uint32_t mem_type_index = alloc_info->memoryTypeIndex; 1148 bool force_unmappable = false; 1149 VkResult result = VK_SUCCESS; 1150 1151 handle = AHardwareBuffer_getNativeHandle(ahb); 1152 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle); 1153 if (dma_buf_fd < 0) 1154 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 1155 1156 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size, 1157 &mem_type_bits); 1158 if (result != VK_SUCCESS) 1159 return result; 1160 1161 /* If ahb is for an image, finish the deferred image creation first */ 1162 if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) { 1163 struct vn_image *img = vn_image_from_handle(dedicated_info->image); 1164 struct vn_android_image_builder builder; 1165 1166 result = vn_android_get_image_builder(dev, &img->deferred_info->create, 1167 handle, alloc, &builder); 1168 if (result != VK_SUCCESS) 1169 return result; 1170 1171 result = vn_image_init_deferred(dev, &builder.create, img); 1172 if (result != VK_SUCCESS) 1173 return result; 1174 1175 const VkMemoryRequirements *mem_req = 1176 &img->requirements[0].memory.memoryRequirements; 1177 if (alloc_size < mem_req->size) { 1178 vn_log(dev->instance, 1179 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")", 1180 alloc_size, mem_req->size); 1181 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 1182 } 1183 1184 alloc_size = mem_req->size; 1185 1186 /* XXX Workaround before spec issue #2762 gets resolved. If importing an 1187 * internally allocated AHB from the exportable path, memoryTypeIndex is 1188 * undefined while defaulting to zero, which can be incompatible with 1189 * the queried memoryTypeBits from the combined memory requirement and 1190 * dma_buf fd properties. Thus we override the requested memoryTypeIndex 1191 * to an applicable one if existed. 1192 */ 1193 if (internal_ahb) { 1194 if ((mem_type_bits & mem_req->memoryTypeBits) == 0) { 1195 vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)", 1196 mem_req->memoryTypeBits, mem_type_bits); 1197 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 1198 } 1199 1200 mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1; 1201 } 1202 1203 /* XXX Workaround before we use cross-domain backend in minigbm. The 1204 * blob_mem allocated from virgl backend can have a queried guest 1205 * mappable size smaller than the size returned from image memory 1206 * requirement. 1207 */ 1208 force_unmappable = true; 1209 } 1210 1211 if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) { 1212 struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer); 1213 const VkMemoryRequirements *mem_req = 1214 &buf->requirements.memory.memoryRequirements; 1215 if (alloc_size < mem_req->size) { 1216 vn_log(dev->instance, 1217 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")", 1218 alloc_size, mem_req->size); 1219 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 1220 } 1221 1222 alloc_size = mem_req->size; 1223 1224 assert((1 << mem_type_index) & mem_req->memoryTypeBits); 1225 } 1226 1227 assert((1 << mem_type_index) & mem_type_bits); 1228 1229 errno = 0; 1230 dup_fd = os_dupfd_cloexec(dma_buf_fd); 1231 if (dup_fd < 0) 1232 return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS 1233 : VK_ERROR_OUT_OF_HOST_MEMORY; 1234 1235 /* Spec requires AHB export info to be present, so we must strip it. In 1236 * practice, the AHB import path here only needs the main allocation info 1237 * and the dedicated_info. 1238 */ 1239 VkMemoryDedicatedAllocateInfo local_dedicated_info; 1240 /* Override when dedicated_info exists and is not the tail struct. */ 1241 if (dedicated_info && dedicated_info->pNext) { 1242 local_dedicated_info = *dedicated_info; 1243 local_dedicated_info.pNext = NULL; 1244 dedicated_info = &local_dedicated_info; 1245 } 1246 const VkMemoryAllocateInfo local_alloc_info = { 1247 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 1248 .pNext = dedicated_info, 1249 .allocationSize = alloc_size, 1250 .memoryTypeIndex = mem_type_index, 1251 }; 1252 result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info, 1253 force_unmappable, dup_fd); 1254 if (result != VK_SUCCESS) { 1255 close(dup_fd); 1256 return result; 1257 } 1258 1259 AHardwareBuffer_acquire(ahb); 1260 mem->ahb = ahb; 1261 1262 return VK_SUCCESS; 1263} 1264 1265VkResult 1266vn_android_device_allocate_ahb(struct vn_device *dev, 1267 struct vn_device_memory *mem, 1268 const VkMemoryAllocateInfo *alloc_info, 1269 const VkAllocationCallbacks *alloc) 1270{ 1271 const VkMemoryDedicatedAllocateInfo *dedicated_info = 1272 vk_find_struct_const(alloc_info->pNext, MEMORY_DEDICATED_ALLOCATE_INFO); 1273 uint32_t width = 0; 1274 uint32_t height = 1; 1275 uint32_t layers = 1; 1276 uint32_t format = 0; 1277 uint64_t usage = 0; 1278 struct AHardwareBuffer *ahb = NULL; 1279 1280 if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) { 1281 const VkImageCreateInfo *image_info = 1282 &vn_image_from_handle(dedicated_info->image)->deferred_info->create; 1283 assert(image_info); 1284 width = image_info->extent.width; 1285 height = image_info->extent.height; 1286 layers = image_info->arrayLayers; 1287 format = vn_android_ahb_format_from_vk_format(image_info->format); 1288 usage = vn_android_get_ahb_usage(image_info->usage, image_info->flags); 1289 } else { 1290 const VkPhysicalDeviceMemoryProperties *mem_props = 1291 &dev->physical_device->memory_properties.memoryProperties; 1292 1293 assert(alloc_info->memoryTypeIndex < mem_props->memoryTypeCount); 1294 1295 width = alloc_info->allocationSize; 1296 format = AHARDWAREBUFFER_FORMAT_BLOB; 1297 usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER; 1298 if (mem_props->memoryTypes[alloc_info->memoryTypeIndex].propertyFlags & 1299 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { 1300 usage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | 1301 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY; 1302 } 1303 } 1304 1305 ahb = vn_android_ahb_allocate(width, height, layers, format, usage); 1306 if (!ahb) 1307 return VK_ERROR_OUT_OF_HOST_MEMORY; 1308 1309 VkResult result = 1310 vn_android_device_import_ahb(dev, mem, alloc_info, alloc, ahb, true); 1311 1312 /* ahb alloc has already acquired a ref and import will acquire another, 1313 * must release one here to avoid leak. 1314 */ 1315 AHardwareBuffer_release(ahb); 1316 1317 return result; 1318} 1319 1320void 1321vn_android_release_ahb(struct AHardwareBuffer *ahb) 1322{ 1323 AHardwareBuffer_release(ahb); 1324} 1325 1326VkResult 1327vn_GetMemoryAndroidHardwareBufferANDROID( 1328 VkDevice device, 1329 const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, 1330 struct AHardwareBuffer **pBuffer) 1331{ 1332 struct vn_device_memory *mem = vn_device_memory_from_handle(pInfo->memory); 1333 1334 AHardwareBuffer_acquire(mem->ahb); 1335 *pBuffer = mem->ahb; 1336 1337 return VK_SUCCESS; 1338} 1339 1340struct vn_android_buffer_create_info { 1341 VkBufferCreateInfo create; 1342 VkExternalMemoryBufferCreateInfo external; 1343 VkBufferOpaqueCaptureAddressCreateInfo address; 1344}; 1345 1346static const VkBufferCreateInfo * 1347vn_android_fix_buffer_create_info( 1348 const VkBufferCreateInfo *create_info, 1349 struct vn_android_buffer_create_info *local_info) 1350{ 1351 local_info->create = *create_info; 1352 VkBaseOutStructure *dst = (void *)&local_info->create; 1353 1354 vk_foreach_struct_const(src, create_info->pNext) { 1355 void *pnext = NULL; 1356 switch (src->sType) { 1357 case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO: 1358 memcpy(&local_info->external, src, sizeof(local_info->external)); 1359 local_info->external.handleTypes = 1360 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 1361 pnext = &local_info->external; 1362 break; 1363 case VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO: 1364 memcpy(&local_info->address, src, sizeof(local_info->address)); 1365 pnext = &local_info->address; 1366 break; 1367 default: 1368 break; 1369 } 1370 1371 if (pnext) { 1372 dst->pNext = pnext; 1373 dst = pnext; 1374 } 1375 } 1376 1377 dst->pNext = NULL; 1378 1379 return &local_info->create; 1380} 1381 1382VkResult 1383vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev, 1384 uint32_t *out_mem_type_bits) 1385{ 1386 const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB; 1387 /* ensure dma_buf_memory_type_bits covers host visible usage */ 1388 const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER | 1389 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | 1390 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY; 1391 AHardwareBuffer *ahb = NULL; 1392 int dma_buf_fd = -1; 1393 uint64_t alloc_size = 0; 1394 uint32_t mem_type_bits = 0; 1395 VkResult result; 1396 1397 ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage); 1398 if (!ahb) 1399 return VK_ERROR_OUT_OF_HOST_MEMORY; 1400 1401 dma_buf_fd = 1402 vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb)); 1403 if (dma_buf_fd < 0) { 1404 AHardwareBuffer_release(ahb); 1405 return VK_ERROR_INVALID_EXTERNAL_HANDLE; 1406 } 1407 1408 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size, 1409 &mem_type_bits); 1410 1411 AHardwareBuffer_release(ahb); 1412 1413 if (result != VK_SUCCESS) 1414 return result; 1415 1416 *out_mem_type_bits = mem_type_bits; 1417 1418 return VK_SUCCESS; 1419} 1420 1421VkResult 1422vn_android_buffer_from_ahb(struct vn_device *dev, 1423 const VkBufferCreateInfo *create_info, 1424 const VkAllocationCallbacks *alloc, 1425 struct vn_buffer **out_buf) 1426{ 1427 struct vn_android_buffer_create_info local_info; 1428 VkResult result; 1429 1430 create_info = vn_android_fix_buffer_create_info(create_info, &local_info); 1431 result = vn_buffer_create(dev, create_info, alloc, out_buf); 1432 if (result != VK_SUCCESS) 1433 return result; 1434 1435 /* AHB backed buffer layers on top of dma_buf, so here we must comine the 1436 * queried type bits from both buffer memory requirement and dma_buf fd 1437 * properties. 1438 */ 1439 (*out_buf)->requirements.memory.memoryRequirements.memoryTypeBits &= 1440 dev->buffer_cache.ahb_mem_type_bits; 1441 1442 assert((*out_buf)->requirements.memory.memoryRequirements.memoryTypeBits); 1443 1444 return VK_SUCCESS; 1445} 1446