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/hwvulkan.h>
15 #include <vndk/hardware_buffer.h>
16 #include <vulkan/vk_icd.h>
17
18 #include "util/os_file.h"
19 #include "util/u_gralloc/u_gralloc.h"
20 #include "vk_android.h"
21
22 #include "vn_buffer.h"
23 #include "vn_device.h"
24 #include "vn_device_memory.h"
25 #include "vn_image.h"
26 #include "vn_instance.h"
27 #include "vn_physical_device.h"
28 #include "vn_queue.h"
29
30 struct vn_android_gralloc {
31 struct u_gralloc *gralloc;
32 uint64_t front_rendering_usage;
33 };
34
35 static struct vn_android_gralloc _vn_android_gralloc;
36
37 static int
vn_android_gralloc_init()38 vn_android_gralloc_init()
39 {
40 assert(!_vn_android_gralloc.gralloc);
41
42 struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO);
43 if (!gralloc) {
44 vn_log(NULL, "u_gralloc failed to create a gralloc module instance");
45 return -1;
46 }
47
48 const int gralloc_type = u_gralloc_get_type(gralloc);
49 if (gralloc_type != U_GRALLOC_TYPE_CROS &&
50 gralloc_type != U_GRALLOC_TYPE_GRALLOC4) {
51 u_gralloc_destroy(&gralloc);
52 vn_log(NULL, "only CrOS and IMapper v4 grallocs are supported for "
53 "Venus Vulkan HAL");
54 return -1;
55 }
56
57 _vn_android_gralloc.gralloc = gralloc;
58
59 return 0;
60 }
61
62 static inline void
vn_android_gralloc_fini()63 vn_android_gralloc_fini()
64 {
65 u_gralloc_destroy(&_vn_android_gralloc.gralloc);
66 }
67
68 static void
vn_android_gralloc_shared_present_usage_init_once()69 vn_android_gralloc_shared_present_usage_init_once()
70 {
71 assert(_vn_android_gralloc.gralloc);
72
73 int ret = u_gralloc_get_front_rendering_usage(
74 _vn_android_gralloc.gralloc,
75 &_vn_android_gralloc.front_rendering_usage);
76
77 if (ret == 0)
78 assert(_vn_android_gralloc.front_rendering_usage);
79 }
80
81 uint64_t
vn_android_gralloc_get_shared_present_usage()82 vn_android_gralloc_get_shared_present_usage()
83 {
84 static once_flag once = ONCE_FLAG_INIT;
85 call_once(&once, vn_android_gralloc_shared_present_usage_init_once);
86 return _vn_android_gralloc.front_rendering_usage;
87 }
88
89 struct vn_android_gralloc_buffer_properties {
90 uint32_t drm_fourcc;
91 uint32_t num_planes;
92 uint64_t modifier;
93
94 /* plane order matches VkImageDrmFormatModifierExplicitCreateInfoEXT */
95 uint32_t offset[4];
96 uint32_t stride[4];
97 };
98
99 static bool
vn_android_gralloc_get_buffer_properties(buffer_handle_t handle,struct vn_android_gralloc_buffer_properties * out_props)100 vn_android_gralloc_get_buffer_properties(
101 buffer_handle_t handle,
102 struct vn_android_gralloc_buffer_properties *out_props)
103 {
104 struct u_gralloc *gralloc = _vn_android_gralloc.gralloc;
105 struct u_gralloc_buffer_basic_info info;
106
107 /*
108 * We only support (and care of) CrOS and IMapper v4 gralloc modules
109 * at this point. They don't need the pixel stride and HAL format
110 * to be provided externally to them. It allows integrating u_gralloc
111 * with minimal modifications at this point.
112 */
113 struct u_gralloc_buffer_handle ugb_handle = {
114 .handle = handle,
115 .pixel_stride = 0,
116 .hal_format = 0,
117 };
118
119 if (u_gralloc_get_buffer_basic_info(gralloc, &ugb_handle, &info) != 0) {
120 vn_log(NULL, "u_gralloc_get_buffer_basic_info failed");
121 return false;
122 }
123
124 if (info.modifier == DRM_FORMAT_MOD_INVALID) {
125 vn_log(NULL, "Unexpected DRM_FORMAT_MOD_INVALID");
126 return false;
127 }
128
129 assert(info.num_planes <= 4);
130
131 out_props->drm_fourcc = info.drm_fourcc;
132 out_props->num_planes = info.num_planes;
133 for (uint32_t i = 0; i < info.num_planes; i++) {
134 if (!info.strides[i]) {
135 out_props->num_planes = i;
136 break;
137 }
138 out_props->stride[i] = info.strides[i];
139 out_props->offset[i] = info.offsets[i];
140 }
141
142 /* YVU420 has a chroma order of CrCb. So we must swap the planes for CrCb
143 * to align with VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM. This is to serve
144 * VkImageDrmFormatModifierExplicitCreateInfoEXT explicit plane layouts.
145 */
146 if (info.drm_fourcc == DRM_FORMAT_YVU420) {
147 out_props->stride[1] = info.strides[2];
148 out_props->offset[1] = info.offsets[2];
149 out_props->stride[2] = info.strides[1];
150 out_props->offset[2] = info.offsets[1];
151 }
152
153 out_props->modifier = info.modifier;
154
155 return true;
156 }
157
158 static int
vn_android_gralloc_get_dma_buf_fd(const native_handle_t * handle)159 vn_android_gralloc_get_dma_buf_fd(const native_handle_t *handle)
160 {
161 /* There can be multiple fds wrapped inside a native_handle_t, but we
162 * expect the 1st one pointing to the dma_buf. For multi-planar format,
163 * there should only exist one undelying dma_buf. The other fd(s) could be
164 * dups to the same dma_buf or point to the shared memory used to store
165 * gralloc buffer metadata.
166 */
167 assert(handle);
168
169 if (handle->numFds < 1) {
170 vn_log(NULL, "handle->numFds is %d, expected >= 1", handle->numFds);
171 return -1;
172 }
173
174 if (handle->data[0] < 0) {
175 vn_log(NULL, "handle->data[0] < 0");
176 return -1;
177 }
178
179 return handle->data[0];
180 }
181
182 static int
183 vn_hal_open(const struct hw_module_t *mod,
184 const char *id,
185 struct hw_device_t **dev);
186
187 static_assert(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC, "");
188
189 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
190 .common = {
191 .tag = HARDWARE_MODULE_TAG,
192 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
193 .hal_api_version = HARDWARE_HAL_API_VERSION,
194 .id = HWVULKAN_HARDWARE_MODULE_ID,
195 .name = "Venus Vulkan HAL",
196 .author = "Google LLC",
197 .methods = &(hw_module_methods_t) {
198 .open = vn_hal_open,
199 },
200 },
201 };
202
203 static int
vn_hal_close(UNUSED struct hw_device_t * dev)204 vn_hal_close(UNUSED struct hw_device_t *dev)
205 {
206 vn_android_gralloc_fini();
207 return 0;
208 }
209
210 static hwvulkan_device_t vn_hal_dev = {
211 .common = {
212 .tag = HARDWARE_DEVICE_TAG,
213 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
214 .module = &HAL_MODULE_INFO_SYM.common,
215 .close = vn_hal_close,
216 },
217 .EnumerateInstanceExtensionProperties = vn_EnumerateInstanceExtensionProperties,
218 .CreateInstance = vn_CreateInstance,
219 .GetInstanceProcAddr = vn_GetInstanceProcAddr,
220 };
221
222 static int
vn_hal_open(const struct hw_module_t * mod,const char * id,struct hw_device_t ** dev)223 vn_hal_open(const struct hw_module_t *mod,
224 const char *id,
225 struct hw_device_t **dev)
226 {
227 int ret;
228
229 assert(mod == &HAL_MODULE_INFO_SYM.common);
230 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
231
232 ret = vn_android_gralloc_init();
233 if (ret)
234 return ret;
235
236 *dev = &vn_hal_dev.common;
237
238 return 0;
239 }
240
241 const VkFormat *
vn_android_format_to_view_formats(VkFormat format,uint32_t * out_count)242 vn_android_format_to_view_formats(VkFormat format, uint32_t *out_count)
243 {
244 /* For AHB image prop query and creation, venus overrides the tiling to
245 * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, which requires to chain
246 * VkImageFormatListCreateInfo struct in the corresponding pNext when the
247 * VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT is set. Those AHB images are assumed
248 * to be mutable no more than sRGB-ness, and the implementations can fail
249 * whenever going beyond.
250 *
251 * This helper provides the view formats that have sRGB variants for the
252 * image format that venus supports.
253 */
254 static const VkFormat view_formats_r8g8b8a8[] = {
255 VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB
256 };
257 static const VkFormat view_formats_r8g8b8[] = { VK_FORMAT_R8G8B8_UNORM,
258 VK_FORMAT_R8G8B8_SRGB };
259
260 switch (format) {
261 case VK_FORMAT_R8G8B8A8_UNORM:
262 *out_count = ARRAY_SIZE(view_formats_r8g8b8a8);
263 return view_formats_r8g8b8a8;
264 break;
265 case VK_FORMAT_R8G8B8_UNORM:
266 *out_count = ARRAY_SIZE(view_formats_r8g8b8);
267 return view_formats_r8g8b8;
268 break;
269 default:
270 /* let the caller handle the fallback case */
271 *out_count = 0;
272 return NULL;
273 }
274 }
275
276 VkFormat
vn_android_drm_format_to_vk_format(uint32_t format)277 vn_android_drm_format_to_vk_format(uint32_t format)
278 {
279 switch (format) {
280 case DRM_FORMAT_ABGR8888:
281 case DRM_FORMAT_XBGR8888:
282 return VK_FORMAT_R8G8B8A8_UNORM;
283 case DRM_FORMAT_BGR888:
284 return VK_FORMAT_R8G8B8_UNORM;
285 case DRM_FORMAT_RGB565:
286 return VK_FORMAT_R5G6B5_UNORM_PACK16;
287 case DRM_FORMAT_ABGR16161616F:
288 return VK_FORMAT_R16G16B16A16_SFLOAT;
289 case DRM_FORMAT_ABGR2101010:
290 return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
291 case DRM_FORMAT_YVU420:
292 return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
293 case DRM_FORMAT_NV12:
294 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
295 default:
296 return VK_FORMAT_UNDEFINED;
297 }
298 }
299
300 static bool
vn_android_drm_format_is_yuv(uint32_t format)301 vn_android_drm_format_is_yuv(uint32_t format)
302 {
303 assert(vn_android_drm_format_to_vk_format(format) != VK_FORMAT_UNDEFINED);
304
305 switch (format) {
306 case DRM_FORMAT_YVU420:
307 case DRM_FORMAT_NV12:
308 return true;
309 default:
310 return false;
311 }
312 }
313
314 VkResult
vn_GetSwapchainGrallocUsage2ANDROID(VkDevice device,VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * grallocConsumerUsage,uint64_t * grallocProducerUsage)315 vn_GetSwapchainGrallocUsage2ANDROID(
316 VkDevice device,
317 VkFormat format,
318 VkImageUsageFlags imageUsage,
319 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
320 uint64_t *grallocConsumerUsage,
321 uint64_t *grallocProducerUsage)
322 {
323 struct vn_device *dev = vn_device_from_handle(device);
324
325 if (VN_DEBUG(WSI)) {
326 vn_log(dev->instance,
327 "format=%d, imageUsage=0x%x, swapchainImageUsage=0x%x", format,
328 imageUsage, swapchainImageUsage);
329 }
330
331 *grallocConsumerUsage = 0;
332 *grallocProducerUsage = 0;
333 if (imageUsage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
334 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
335 *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
336
337 if (imageUsage &
338 (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
339 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
340 *grallocProducerUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
341
342 if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
343 *grallocProducerUsage |= vn_android_gralloc_get_shared_present_usage();
344
345 vn_tls_set_async_pipeline_create();
346
347 return VK_SUCCESS;
348 }
349
350 static VkResult
vn_android_get_modifier_properties(struct vn_device * dev,VkFormat format,uint64_t modifier,VkDrmFormatModifierPropertiesEXT * out_props)351 vn_android_get_modifier_properties(struct vn_device *dev,
352 VkFormat format,
353 uint64_t modifier,
354 VkDrmFormatModifierPropertiesEXT *out_props)
355 {
356 VkPhysicalDevice physical_device =
357 vn_physical_device_to_handle(dev->physical_device);
358 VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
359 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
360 };
361 VkFormatProperties2 format_prop = {
362 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
363 .pNext = &mod_prop_list,
364 };
365
366 vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
367 &format_prop);
368
369 if (!mod_prop_list.drmFormatModifierCount) {
370 vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
371 format);
372 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
373 }
374
375 STACK_ARRAY(VkDrmFormatModifierPropertiesEXT, mod_props,
376 mod_prop_list.drmFormatModifierCount);
377
378 mod_prop_list.pDrmFormatModifierProperties = mod_props;
379 vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
380 &format_prop);
381
382 bool modifier_found = false;
383 for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
384 if (mod_props[i].drmFormatModifier == modifier) {
385 *out_props = mod_props[i];
386 modifier_found = true;
387 break;
388 }
389 }
390
391 STACK_ARRAY_FINISH(mod_props);
392
393 if (!modifier_found) {
394 vn_log(dev->instance,
395 "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
396 modifier, format);
397 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
398 }
399
400 return VK_SUCCESS;
401 }
402
403 struct vn_android_image_builder {
404 VkImageCreateInfo create;
405 VkSubresourceLayout layouts[4];
406 VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
407 VkExternalMemoryImageCreateInfo external;
408 VkImageFormatListCreateInfo list;
409 };
410
411 static VkResult
vn_android_get_image_builder(struct vn_device * dev,const VkImageCreateInfo * create_info,const native_handle_t * handle,struct vn_android_image_builder * out_builder)412 vn_android_get_image_builder(struct vn_device *dev,
413 const VkImageCreateInfo *create_info,
414 const native_handle_t *handle,
415 struct vn_android_image_builder *out_builder)
416 {
417 /* Android image builder is only used by ANB or AHB. For ANB, Android
418 * Vulkan loader will never pass the below structs. For AHB, struct
419 * vn_image_create_deferred_info will never carry below either.
420 */
421 assert(!vk_find_struct_const(
422 create_info->pNext,
423 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT));
424 assert(!vk_find_struct_const(create_info->pNext,
425 EXTERNAL_MEMORY_IMAGE_CREATE_INFO));
426
427 struct vn_android_gralloc_buffer_properties buf_props;
428 if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props))
429 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
430
431 /* fill VkImageCreateInfo */
432 memset(out_builder, 0, sizeof(*out_builder));
433 out_builder->create = *create_info;
434 out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
435
436 /* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */
437 for (uint32_t i = 0; i < buf_props.num_planes; i++) {
438 out_builder->layouts[i].offset = buf_props.offset[i];
439 out_builder->layouts[i].rowPitch = buf_props.stride[i];
440 }
441 out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
442 .sType =
443 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
444 .pNext = out_builder->create.pNext,
445 .drmFormatModifier = buf_props.modifier,
446 .drmFormatModifierPlaneCount = buf_props.num_planes,
447 .pPlaneLayouts = out_builder->layouts,
448 };
449 out_builder->create.pNext = &out_builder->modifier;
450
451 /* fill VkExternalMemoryImageCreateInfo */
452 out_builder->external = (VkExternalMemoryImageCreateInfo){
453 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
454 .pNext = out_builder->create.pNext,
455 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
456 };
457 out_builder->create.pNext = &out_builder->external;
458
459 /* fill VkImageFormatListCreateInfo if needed
460 *
461 * vn_image::deferred_info only stores VkImageFormatListCreateInfo with a
462 * non-zero viewFormatCount, and that stored struct will be respected.
463 */
464 if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
465 !vk_find_struct_const(create_info->pNext,
466 IMAGE_FORMAT_LIST_CREATE_INFO)) {
467 /* 12.3. Images
468 *
469 * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags
470 * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain
471 * must include a VkImageFormatListCreateInfo structure with non-zero
472 * viewFormatCount.
473 */
474 uint32_t vcount = 0;
475 const VkFormat *vformats =
476 vn_android_format_to_view_formats(create_info->format, &vcount);
477 if (!vformats) {
478 /* image builder struct persists through the image creation call */
479 vformats = &out_builder->create.format;
480 vcount = 1;
481 }
482 out_builder->list = (VkImageFormatListCreateInfo){
483 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
484 .pNext = out_builder->create.pNext,
485 .viewFormatCount = vcount,
486 .pViewFormats = vformats,
487 };
488 out_builder->create.pNext = &out_builder->list;
489 }
490
491 return VK_SUCCESS;
492 }
493
494 static VkResult
vn_android_image_from_anb_internal(struct vn_device * dev,const VkImageCreateInfo * create_info,const VkNativeBufferANDROID * anb_info,const VkAllocationCallbacks * alloc,struct vn_image ** out_img)495 vn_android_image_from_anb_internal(struct vn_device *dev,
496 const VkImageCreateInfo *create_info,
497 const VkNativeBufferANDROID *anb_info,
498 const VkAllocationCallbacks *alloc,
499 struct vn_image **out_img)
500 {
501 /* If anb_info->handle points to a classic resouce created from
502 * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
503 * guest shadow storage other than the host gpu storage.
504 *
505 * We also need to pass the correct stride to vn_CreateImage, which will be
506 * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
507 * VK_EXT_image_drm_format_modifier support in the host driver. The struct
508 * needs host storage info which can be queried from cros gralloc.
509 */
510 struct vn_image *img = NULL;
511 VkResult result;
512
513 assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
514 assert(!vk_find_struct_const(create_info->pNext,
515 IMAGE_FORMAT_LIST_CREATE_INFO));
516 assert(!vk_find_struct_const(create_info->pNext,
517 IMAGE_STENCIL_USAGE_CREATE_INFO));
518
519 struct vn_android_image_builder builder;
520 result = vn_android_get_image_builder(dev, create_info, anb_info->handle,
521 &builder);
522 if (result != VK_SUCCESS)
523 return result;
524
525 /* encoder will strip the Android specific pNext structs */
526 if (*out_img) {
527 /* driver side img obj has been created for deferred init like ahb */
528 img = *out_img;
529 result = vn_image_init_deferred(dev, &builder.create, img);
530 if (result != VK_SUCCESS) {
531 vn_log(dev->instance, "anb: vn_image_init_deferred failed");
532 return result;
533 }
534 } else {
535 result = vn_image_create(dev, &builder.create, alloc, &img);
536 if (result != VK_SUCCESS) {
537 vn_log(dev->instance, "anb: vn_image_create failed");
538 return result;
539 }
540 }
541
542 img->wsi.is_wsi = true;
543 img->wsi.tiling_override = builder.create.tiling;
544 img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier;
545
546 int dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle);
547 if (dma_buf_fd < 0) {
548 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
549 goto fail;
550 }
551
552 uint64_t alloc_size = 0;
553 uint32_t mem_type_bits = 0;
554 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
555 &mem_type_bits);
556 if (result != VK_SUCCESS)
557 goto fail;
558
559 const VkMemoryRequirements *mem_req =
560 &img->requirements[0].memory.memoryRequirements;
561 if (alloc_size < mem_req->size) {
562 vn_log(dev->instance,
563 "anb: alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
564 alloc_size, mem_req->size);
565 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
566 goto fail;
567 }
568
569 mem_type_bits &= mem_req->memoryTypeBits;
570 if (!mem_type_bits) {
571 vn_log(dev->instance, "anb: no compatible mem type");
572 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
573 goto fail;
574 }
575
576 int dup_fd = os_dupfd_cloexec(dma_buf_fd);
577 if (dup_fd < 0) {
578 vn_log(dev->instance, "anb: os_dupfd_cloexec failed(%d)", errno);
579 result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
580 : VK_ERROR_OUT_OF_HOST_MEMORY;
581 goto fail;
582 }
583
584 const bool prefer_dedicated =
585 img->requirements[0].dedicated.prefersDedicatedAllocation == VK_TRUE;
586 const VkMemoryDedicatedAllocateInfo dedicated_info = {
587 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
588 .image = vn_image_to_handle(img),
589 };
590 const VkImportMemoryFdInfoKHR import_fd_info = {
591 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
592 .pNext = prefer_dedicated ? &dedicated_info : NULL,
593 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
594 .fd = dup_fd,
595 };
596 const VkMemoryAllocateInfo memory_info = {
597 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
598 .pNext = &import_fd_info,
599 .allocationSize = mem_req->size,
600 .memoryTypeIndex = ffs(mem_type_bits) - 1,
601 };
602 VkDeviceMemory mem_handle;
603 result = vn_AllocateMemory(vn_device_to_handle(dev), &memory_info, alloc,
604 &mem_handle);
605 if (result != VK_SUCCESS) {
606 vn_log(dev->instance, "anb: mem import failed");
607 /* only need to close the dup_fd on import failure */
608 close(dup_fd);
609 goto fail;
610 }
611
612 /* Android WSI image owns the memory */
613 img->wsi.memory = vn_device_memory_from_handle(mem_handle);
614 img->wsi.memory_owned = true;
615 *out_img = img;
616
617 return VK_SUCCESS;
618
619 fail:
620 /* this handles mem free for owned import */
621 vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img), alloc);
622 return result;
623 }
624
625 VkResult
vn_android_image_from_anb(struct vn_device * dev,const VkImageCreateInfo * create_info,const VkNativeBufferANDROID * anb_info,const VkAllocationCallbacks * alloc,struct vn_image ** out_img)626 vn_android_image_from_anb(struct vn_device *dev,
627 const VkImageCreateInfo *create_info,
628 const VkNativeBufferANDROID *anb_info,
629 const VkAllocationCallbacks *alloc,
630 struct vn_image **out_img)
631 {
632 struct vn_image *img = NULL;
633 VkResult result = vn_android_image_from_anb_internal(
634 dev, create_info, anb_info, alloc, &img);
635 if (result != VK_SUCCESS)
636 return result;
637
638 const VkBindImageMemoryInfo bind_info = {
639 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
640 .image = vn_image_to_handle(img),
641 .memory = vn_device_memory_to_handle(img->wsi.memory),
642 };
643 result = vn_BindImageMemory2(vn_device_to_handle(dev), 1, &bind_info);
644 if (result != VK_SUCCESS) {
645 vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img),
646 alloc);
647 return result;
648 }
649
650 *out_img = img;
651 return VK_SUCCESS;
652 }
653
654 struct vn_device_memory *
vn_android_get_wsi_memory_from_bind_info(struct vn_device * dev,const VkBindImageMemoryInfo * bind_info)655 vn_android_get_wsi_memory_from_bind_info(
656 struct vn_device *dev, const VkBindImageMemoryInfo *bind_info)
657 {
658 const VkNativeBufferANDROID *anb_info =
659 vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
660 assert(anb_info && anb_info->handle);
661
662 struct vn_image *img = vn_image_from_handle(bind_info->image);
663 VkResult result = vn_android_image_from_anb_internal(
664 dev, &img->deferred_info->create, anb_info, &dev->base.base.alloc,
665 &img);
666 if (result != VK_SUCCESS)
667 return NULL;
668
669 assert(img->wsi.memory_owned);
670 return img->wsi.memory;
671 }
672
673 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)674 vn_android_get_ahb_format_properties(
675 struct vn_device *dev,
676 const struct AHardwareBuffer *ahb,
677 VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
678 {
679 AHardwareBuffer_Desc desc;
680 VkFormat format;
681 struct vn_android_gralloc_buffer_properties buf_props;
682 VkDrmFormatModifierPropertiesEXT mod_props;
683
684 AHardwareBuffer_describe(ahb, &desc);
685 if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
686 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
687 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
688 vn_log(dev->instance,
689 "AHB usage(%" PRIu64 ") must include at least one GPU bit",
690 desc.usage);
691 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
692 }
693
694 /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
695 if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
696 out_props->format = VK_FORMAT_UNDEFINED;
697 return VK_SUCCESS;
698 }
699
700 if (!vn_android_gralloc_get_buffer_properties(
701 AHardwareBuffer_getNativeHandle(ahb), &buf_props))
702 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
703
704 /* We implement AHB extension support with EXT_image_drm_format_modifier.
705 * It requires us to have a compatible VkFormat but not DRM formats. So if
706 * the ahb is not intended for backing a VkBuffer, error out early if the
707 * format is VK_FORMAT_UNDEFINED.
708 */
709 format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
710 if (format == VK_FORMAT_UNDEFINED) {
711 vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
712 buf_props.drm_fourcc, desc.format);
713 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
714 }
715
716 VkResult result = vn_android_get_modifier_properties(
717 dev, format, buf_props.modifier, &mod_props);
718 if (result != VK_SUCCESS)
719 return result;
720
721 if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
722 vn_log(dev->instance,
723 "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
724 "for DRM format modifier(%" PRIu64 ")",
725 mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
726 buf_props.modifier);
727 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
728 }
729
730 /* The spec requires that formatFeatures must include at least one of
731 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
732 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
733 */
734 const VkFormatFeatureFlags format_features =
735 mod_props.drmFormatModifierTilingFeatures |
736 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
737
738 /* 11.2.7. Android Hardware Buffer External Memory
739 *
740 * Implementations may not always be able to determine the color model,
741 * numerical range, or chroma offsets of the image contents, so the values
742 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
743 * Applications should treat these values as sensible defaults to use in the
744 * absence of more reliable information obtained through some other means.
745 */
746 const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
747 const VkSamplerYcbcrModelConversion model =
748 is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
749 : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
750
751 /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
752 * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
753 * AHB formats. Venus supports below explicit ones:
754 * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
755 * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
756 */
757 if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
758 format = VK_FORMAT_UNDEFINED;
759
760 *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
761 .sType = out_props->sType,
762 .pNext = out_props->pNext,
763 .format = format,
764 .externalFormat = buf_props.drm_fourcc,
765 .formatFeatures = format_features,
766 .samplerYcbcrConversionComponents = {
767 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
768 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
769 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
770 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
771 },
772 .suggestedYcbcrModel = model,
773 /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
774 .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
775 .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
776 .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
777 };
778
779 return VK_SUCCESS;
780 }
781
782 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)783 vn_GetAndroidHardwareBufferPropertiesANDROID(
784 VkDevice device,
785 const struct AHardwareBuffer *buffer,
786 VkAndroidHardwareBufferPropertiesANDROID *pProperties)
787 {
788 VN_TRACE_FUNC();
789 struct vn_device *dev = vn_device_from_handle(device);
790 VkResult result = VK_SUCCESS;
791 int dma_buf_fd = -1;
792 uint64_t alloc_size = 0;
793 uint32_t mem_type_bits = 0;
794
795 VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
796 vk_find_struct(pProperties->pNext,
797 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
798 VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
799 vk_find_struct(pProperties->pNext,
800 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
801 if (format_props2 || format_props) {
802 VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
803 .sType =
804 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
805 };
806 if (!format_props)
807 format_props = &local_props;
808
809 result =
810 vn_android_get_ahb_format_properties(dev, buffer, format_props);
811 if (result != VK_SUCCESS)
812 return vn_error(dev->instance, result);
813
814 if (format_props2) {
815 format_props2->format = format_props->format;
816 format_props2->externalFormat = format_props->externalFormat;
817 format_props2->formatFeatures =
818 (VkFormatFeatureFlags2)format_props->formatFeatures;
819 format_props2->samplerYcbcrConversionComponents =
820 format_props->samplerYcbcrConversionComponents;
821 format_props2->suggestedYcbcrModel =
822 format_props->suggestedYcbcrModel;
823 format_props2->suggestedYcbcrRange =
824 format_props->suggestedYcbcrRange;
825 format_props2->suggestedXChromaOffset =
826 format_props->suggestedXChromaOffset;
827 format_props2->suggestedYChromaOffset =
828 format_props->suggestedYChromaOffset;
829 }
830 }
831
832 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
833 AHardwareBuffer_getNativeHandle(buffer));
834 if (dma_buf_fd < 0)
835 return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
836
837 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
838 &mem_type_bits);
839 if (result != VK_SUCCESS)
840 return vn_error(dev->instance, result);
841
842 pProperties->allocationSize = alloc_size;
843 pProperties->memoryTypeBits = mem_type_bits;
844
845 return VK_SUCCESS;
846 }
847
848 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)849 vn_android_ahb_allocate(uint32_t width,
850 uint32_t height,
851 uint32_t layers,
852 uint32_t format,
853 uint64_t usage)
854 {
855 AHardwareBuffer *ahb = NULL;
856 AHardwareBuffer_Desc desc;
857 int ret = 0;
858
859 memset(&desc, 0, sizeof(desc));
860 desc.width = width;
861 desc.height = height;
862 desc.layers = layers;
863 desc.format = format;
864 desc.usage = usage;
865
866 ret = AHardwareBuffer_allocate(&desc, &ahb);
867 if (ret) {
868 /* We just log the error code here for now since the platform falsely
869 * maps all gralloc allocation failures to oom.
870 */
871 vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
872 width, height, layers, format, usage, ret);
873 return NULL;
874 }
875
876 return ahb;
877 }
878
879 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)880 vn_android_get_drm_format_modifier_info(
881 const VkPhysicalDeviceImageFormatInfo2 *format_info,
882 VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
883 {
884 /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
885 * to allocate an ahb to retrieve the drm format modifier. For the image
886 * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
887 */
888 AHardwareBuffer *ahb = NULL;
889 uint32_t format = 0;
890 uint64_t usage = 0;
891 struct vn_android_gralloc_buffer_properties buf_props;
892
893 assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
894
895 format = vk_image_format_to_ahb_format(format_info->format);
896 if (!format)
897 return false;
898
899 usage =
900 vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
901 ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
902 if (!ahb)
903 return false;
904
905 if (!vn_android_gralloc_get_buffer_properties(
906 AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
907 AHardwareBuffer_release(ahb);
908 return false;
909 }
910
911 *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
912 .sType =
913 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
914 .pNext = NULL,
915 .drmFormatModifier = buf_props.modifier,
916 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
917 .queueFamilyIndexCount = 0,
918 .pQueueFamilyIndices = NULL,
919 };
920
921 AHardwareBuffer_release(ahb);
922 return true;
923 }
924
925 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)926 vn_android_device_import_ahb(
927 struct vn_device *dev,
928 struct vn_device_memory *mem,
929 const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
930 {
931 const struct vk_device_memory *mem_vk = &mem->base.base;
932 const native_handle_t *handle = NULL;
933 int dma_buf_fd = -1;
934 int dup_fd = -1;
935 uint64_t alloc_size = 0;
936 uint32_t mem_type_bits = 0;
937 uint32_t mem_type_index = mem_vk->memory_type_index;
938 bool force_unmappable = false;
939 VkResult result = VK_SUCCESS;
940
941 handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
942 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
943 if (dma_buf_fd < 0)
944 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
945
946 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
947 &mem_type_bits);
948 if (result != VK_SUCCESS)
949 return result;
950
951 /* If ahb is for an image, finish the deferred image creation first */
952 if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
953 struct vn_image *img = vn_image_from_handle(dedicated_info->image);
954 struct vn_android_image_builder builder;
955
956 result = vn_android_get_image_builder(dev, &img->deferred_info->create,
957 handle, &builder);
958 if (result != VK_SUCCESS)
959 return result;
960
961 result = vn_image_init_deferred(dev, &builder.create, img);
962 if (result != VK_SUCCESS)
963 return result;
964
965 const VkMemoryRequirements *mem_req =
966 &img->requirements[0].memory.memoryRequirements;
967 if (alloc_size < mem_req->size) {
968 vn_log(dev->instance,
969 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
970 alloc_size, mem_req->size);
971 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
972 }
973
974 alloc_size = mem_req->size;
975
976 /* Per spec 11.2.3. Device Memory Allocation
977 *
978 * If the parameters define an export operation and the external handle
979 * type is
980 * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
981 * implementations should not strictly follow memoryTypeIndex. Instead,
982 * they should modify the allocation internally to use the required
983 * memory type for the application’s given usage. This is because for an
984 * export operation, there is currently no way for the client to know
985 * the memory type index before allocating.
986 */
987 if (!(mem_vk->import_handle_type &
988 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
989 if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
990 vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
991 mem_req->memoryTypeBits, mem_type_bits);
992 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
993 }
994
995 mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
996 }
997
998 /* XXX Workaround before we use cross-domain backend in minigbm. The
999 * blob_mem allocated from virgl backend can have a queried guest
1000 * mappable size smaller than the size returned from image memory
1001 * requirement.
1002 */
1003 force_unmappable = true;
1004 }
1005
1006 if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
1007 struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
1008 const VkMemoryRequirements *mem_req =
1009 &buf->requirements.memory.memoryRequirements;
1010 if (alloc_size < mem_req->size) {
1011 vn_log(dev->instance,
1012 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
1013 alloc_size, mem_req->size);
1014 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1015 }
1016
1017 alloc_size = mem_req->size;
1018
1019 assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1020 }
1021
1022 assert((1 << mem_type_index) & mem_type_bits);
1023
1024 errno = 0;
1025 dup_fd = os_dupfd_cloexec(dma_buf_fd);
1026 if (dup_fd < 0)
1027 return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1028 : VK_ERROR_OUT_OF_HOST_MEMORY;
1029
1030 /* Spec requires AHB export info to be present, so we must strip it. In
1031 * practice, the AHB import path here only needs the main allocation info
1032 * and the dedicated_info.
1033 */
1034 VkMemoryDedicatedAllocateInfo local_dedicated_info;
1035 /* Override when dedicated_info exists and is not the tail struct. */
1036 if (dedicated_info && dedicated_info->pNext) {
1037 local_dedicated_info = *dedicated_info;
1038 local_dedicated_info.pNext = NULL;
1039 dedicated_info = &local_dedicated_info;
1040 }
1041 const VkMemoryAllocateInfo local_alloc_info = {
1042 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1043 .pNext = dedicated_info,
1044 .allocationSize = alloc_size,
1045 .memoryTypeIndex = mem_type_index,
1046 };
1047 result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1048 force_unmappable, dup_fd);
1049 if (result != VK_SUCCESS) {
1050 close(dup_fd);
1051 return result;
1052 }
1053
1054 return VK_SUCCESS;
1055 }
1056
1057 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1058 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1059 {
1060 static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1061 /* ensure dma_buf_memory_type_bits covers host visible usage */
1062 static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1063 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1064 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1065 AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1066 if (!ahb)
1067 return 0;
1068
1069 int dma_buf_fd =
1070 vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1071 if (dma_buf_fd < 0) {
1072 AHardwareBuffer_release(ahb);
1073 return 0;
1074 }
1075
1076 uint64_t alloc_size = 0;
1077 uint32_t mem_type_bits = 0;
1078 VkResult ret = vn_get_memory_dma_buf_properties(
1079 dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1080 /* release ahb first as below no longer needs it */
1081 AHardwareBuffer_release(ahb);
1082
1083 if (ret != VK_SUCCESS) {
1084 vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1085 return 0;
1086 }
1087
1088 return mem_type_bits;
1089 }
1090