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 VkImportMemoryFdInfoKHR import_fd_info = {
585 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
586 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
587 .fd = dup_fd,
588 };
589 const VkMemoryAllocateInfo memory_info = {
590 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
591 .pNext = &import_fd_info,
592 .allocationSize = mem_req->size,
593 .memoryTypeIndex = ffs(mem_type_bits) - 1,
594 };
595 VkDeviceMemory mem_handle;
596 result = vn_AllocateMemory(vn_device_to_handle(dev), &memory_info, alloc,
597 &mem_handle);
598 if (result != VK_SUCCESS) {
599 vn_log(dev->instance, "anb: mem import failed");
600 /* only need to close the dup_fd on import failure */
601 close(dup_fd);
602 goto fail;
603 }
604
605 /* Android WSI image owns the memory */
606 img->wsi.memory = vn_device_memory_from_handle(mem_handle);
607 img->wsi.memory_owned = true;
608 *out_img = img;
609
610 return VK_SUCCESS;
611
612 fail:
613 /* this handles mem free for owned import */
614 vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img), alloc);
615 return result;
616 }
617
618 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)619 vn_android_image_from_anb(struct vn_device *dev,
620 const VkImageCreateInfo *create_info,
621 const VkNativeBufferANDROID *anb_info,
622 const VkAllocationCallbacks *alloc,
623 struct vn_image **out_img)
624 {
625 struct vn_image *img = NULL;
626 VkResult result = vn_android_image_from_anb_internal(
627 dev, create_info, anb_info, alloc, &img);
628 if (result != VK_SUCCESS)
629 return result;
630
631 const VkBindImageMemoryInfo bind_info = {
632 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
633 .image = vn_image_to_handle(img),
634 .memory = vn_device_memory_to_handle(img->wsi.memory),
635 };
636 result = vn_BindImageMemory2(vn_device_to_handle(dev), 1, &bind_info);
637 if (result != VK_SUCCESS) {
638 vn_DestroyImage(vn_device_to_handle(dev), vn_image_to_handle(img),
639 alloc);
640 return result;
641 }
642
643 *out_img = img;
644 return VK_SUCCESS;
645 }
646
647 struct vn_device_memory *
vn_android_get_wsi_memory_from_bind_info(struct vn_device * dev,const VkBindImageMemoryInfo * bind_info)648 vn_android_get_wsi_memory_from_bind_info(
649 struct vn_device *dev, const VkBindImageMemoryInfo *bind_info)
650 {
651 const VkNativeBufferANDROID *anb_info =
652 vk_find_struct_const(bind_info->pNext, NATIVE_BUFFER_ANDROID);
653 assert(anb_info && anb_info->handle);
654
655 struct vn_image *img = vn_image_from_handle(bind_info->image);
656 VkResult result = vn_android_image_from_anb_internal(
657 dev, &img->deferred_info->create, anb_info, &dev->base.base.alloc,
658 &img);
659 if (result != VK_SUCCESS)
660 return NULL;
661
662 assert(img->wsi.memory_owned);
663 return img->wsi.memory;
664 }
665
666 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)667 vn_android_get_ahb_format_properties(
668 struct vn_device *dev,
669 const struct AHardwareBuffer *ahb,
670 VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
671 {
672 AHardwareBuffer_Desc desc;
673 VkFormat format;
674 struct vn_android_gralloc_buffer_properties buf_props;
675 VkDrmFormatModifierPropertiesEXT mod_props;
676
677 AHardwareBuffer_describe(ahb, &desc);
678 if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
679 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
680 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
681 vn_log(dev->instance,
682 "AHB usage(%" PRIu64 ") must include at least one GPU bit",
683 desc.usage);
684 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
685 }
686
687 /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
688 if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
689 out_props->format = VK_FORMAT_UNDEFINED;
690 return VK_SUCCESS;
691 }
692
693 if (!vn_android_gralloc_get_buffer_properties(
694 AHardwareBuffer_getNativeHandle(ahb), &buf_props))
695 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
696
697 /* We implement AHB extension support with EXT_image_drm_format_modifier.
698 * It requires us to have a compatible VkFormat but not DRM formats. So if
699 * the ahb is not intended for backing a VkBuffer, error out early if the
700 * format is VK_FORMAT_UNDEFINED.
701 */
702 format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
703 if (format == VK_FORMAT_UNDEFINED) {
704 vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
705 buf_props.drm_fourcc, desc.format);
706 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
707 }
708
709 VkResult result = vn_android_get_modifier_properties(
710 dev, format, buf_props.modifier, &mod_props);
711 if (result != VK_SUCCESS)
712 return result;
713
714 if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
715 vn_log(dev->instance,
716 "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
717 "for DRM format modifier(%" PRIu64 ")",
718 mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
719 buf_props.modifier);
720 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
721 }
722
723 /* The spec requires that formatFeatures must include at least one of
724 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
725 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
726 */
727 const VkFormatFeatureFlags format_features =
728 mod_props.drmFormatModifierTilingFeatures |
729 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
730
731 /* 11.2.7. Android Hardware Buffer External Memory
732 *
733 * Implementations may not always be able to determine the color model,
734 * numerical range, or chroma offsets of the image contents, so the values
735 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
736 * Applications should treat these values as sensible defaults to use in the
737 * absence of more reliable information obtained through some other means.
738 */
739 const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
740 const VkSamplerYcbcrModelConversion model =
741 is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
742 : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
743
744 /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
745 * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
746 * AHB formats. Venus supports below explicit ones:
747 * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
748 * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
749 */
750 if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
751 format = VK_FORMAT_UNDEFINED;
752
753 *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
754 .sType = out_props->sType,
755 .pNext = out_props->pNext,
756 .format = format,
757 .externalFormat = buf_props.drm_fourcc,
758 .formatFeatures = format_features,
759 .samplerYcbcrConversionComponents = {
760 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
761 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
762 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
763 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
764 },
765 .suggestedYcbcrModel = model,
766 /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
767 .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
768 .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
769 .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
770 };
771
772 return VK_SUCCESS;
773 }
774
775 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)776 vn_GetAndroidHardwareBufferPropertiesANDROID(
777 VkDevice device,
778 const struct AHardwareBuffer *buffer,
779 VkAndroidHardwareBufferPropertiesANDROID *pProperties)
780 {
781 VN_TRACE_FUNC();
782 struct vn_device *dev = vn_device_from_handle(device);
783 VkResult result = VK_SUCCESS;
784 int dma_buf_fd = -1;
785 uint64_t alloc_size = 0;
786 uint32_t mem_type_bits = 0;
787
788 VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
789 vk_find_struct(pProperties->pNext,
790 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
791 VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
792 vk_find_struct(pProperties->pNext,
793 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
794 if (format_props2 || format_props) {
795 VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
796 .sType =
797 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
798 };
799 if (!format_props)
800 format_props = &local_props;
801
802 result =
803 vn_android_get_ahb_format_properties(dev, buffer, format_props);
804 if (result != VK_SUCCESS)
805 return vn_error(dev->instance, result);
806
807 if (format_props2) {
808 format_props2->format = format_props->format;
809 format_props2->externalFormat = format_props->externalFormat;
810 format_props2->formatFeatures =
811 (VkFormatFeatureFlags2)format_props->formatFeatures;
812 format_props2->samplerYcbcrConversionComponents =
813 format_props->samplerYcbcrConversionComponents;
814 format_props2->suggestedYcbcrModel =
815 format_props->suggestedYcbcrModel;
816 format_props2->suggestedYcbcrRange =
817 format_props->suggestedYcbcrRange;
818 format_props2->suggestedXChromaOffset =
819 format_props->suggestedXChromaOffset;
820 format_props2->suggestedYChromaOffset =
821 format_props->suggestedYChromaOffset;
822 }
823 }
824
825 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
826 AHardwareBuffer_getNativeHandle(buffer));
827 if (dma_buf_fd < 0)
828 return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
829
830 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
831 &mem_type_bits);
832 if (result != VK_SUCCESS)
833 return vn_error(dev->instance, result);
834
835 pProperties->allocationSize = alloc_size;
836 pProperties->memoryTypeBits = mem_type_bits;
837
838 return VK_SUCCESS;
839 }
840
841 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)842 vn_android_ahb_allocate(uint32_t width,
843 uint32_t height,
844 uint32_t layers,
845 uint32_t format,
846 uint64_t usage)
847 {
848 AHardwareBuffer *ahb = NULL;
849 AHardwareBuffer_Desc desc;
850 int ret = 0;
851
852 memset(&desc, 0, sizeof(desc));
853 desc.width = width;
854 desc.height = height;
855 desc.layers = layers;
856 desc.format = format;
857 desc.usage = usage;
858
859 ret = AHardwareBuffer_allocate(&desc, &ahb);
860 if (ret) {
861 /* We just log the error code here for now since the platform falsely
862 * maps all gralloc allocation failures to oom.
863 */
864 vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
865 width, height, layers, format, usage, ret);
866 return NULL;
867 }
868
869 return ahb;
870 }
871
872 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)873 vn_android_get_drm_format_modifier_info(
874 const VkPhysicalDeviceImageFormatInfo2 *format_info,
875 VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
876 {
877 /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
878 * to allocate an ahb to retrieve the drm format modifier. For the image
879 * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
880 */
881 AHardwareBuffer *ahb = NULL;
882 uint32_t format = 0;
883 uint64_t usage = 0;
884 struct vn_android_gralloc_buffer_properties buf_props;
885
886 assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
887
888 format = vk_image_format_to_ahb_format(format_info->format);
889 if (!format)
890 return false;
891
892 usage =
893 vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
894 ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
895 if (!ahb)
896 return false;
897
898 if (!vn_android_gralloc_get_buffer_properties(
899 AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
900 AHardwareBuffer_release(ahb);
901 return false;
902 }
903
904 *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
905 .sType =
906 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
907 .pNext = NULL,
908 .drmFormatModifier = buf_props.modifier,
909 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
910 .queueFamilyIndexCount = 0,
911 .pQueueFamilyIndices = NULL,
912 };
913
914 AHardwareBuffer_release(ahb);
915 return true;
916 }
917
918 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)919 vn_android_device_import_ahb(
920 struct vn_device *dev,
921 struct vn_device_memory *mem,
922 const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
923 {
924 const struct vk_device_memory *mem_vk = &mem->base.base;
925 const native_handle_t *handle = NULL;
926 int dma_buf_fd = -1;
927 int dup_fd = -1;
928 uint64_t alloc_size = 0;
929 uint32_t mem_type_bits = 0;
930 uint32_t mem_type_index = mem_vk->memory_type_index;
931 bool force_unmappable = false;
932 VkResult result = VK_SUCCESS;
933
934 handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
935 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
936 if (dma_buf_fd < 0)
937 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
938
939 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
940 &mem_type_bits);
941 if (result != VK_SUCCESS)
942 return result;
943
944 /* If ahb is for an image, finish the deferred image creation first */
945 if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
946 struct vn_image *img = vn_image_from_handle(dedicated_info->image);
947 struct vn_android_image_builder builder;
948
949 result = vn_android_get_image_builder(dev, &img->deferred_info->create,
950 handle, &builder);
951 if (result != VK_SUCCESS)
952 return result;
953
954 result = vn_image_init_deferred(dev, &builder.create, img);
955 if (result != VK_SUCCESS)
956 return result;
957
958 const VkMemoryRequirements *mem_req =
959 &img->requirements[0].memory.memoryRequirements;
960 if (alloc_size < mem_req->size) {
961 vn_log(dev->instance,
962 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
963 alloc_size, mem_req->size);
964 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
965 }
966
967 alloc_size = mem_req->size;
968
969 /* Per spec 11.2.3. Device Memory Allocation
970 *
971 * If the parameters define an export operation and the external handle
972 * type is
973 * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
974 * implementations should not strictly follow memoryTypeIndex. Instead,
975 * they should modify the allocation internally to use the required
976 * memory type for the application’s given usage. This is because for an
977 * export operation, there is currently no way for the client to know
978 * the memory type index before allocating.
979 */
980 if (!(mem_vk->import_handle_type &
981 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
982 if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
983 vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
984 mem_req->memoryTypeBits, mem_type_bits);
985 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
986 }
987
988 mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
989 }
990
991 /* XXX Workaround before we use cross-domain backend in minigbm. The
992 * blob_mem allocated from virgl backend can have a queried guest
993 * mappable size smaller than the size returned from image memory
994 * requirement.
995 */
996 force_unmappable = true;
997 }
998
999 if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
1000 struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
1001 const VkMemoryRequirements *mem_req =
1002 &buf->requirements.memory.memoryRequirements;
1003 if (alloc_size < mem_req->size) {
1004 vn_log(dev->instance,
1005 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
1006 alloc_size, mem_req->size);
1007 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
1008 }
1009
1010 alloc_size = mem_req->size;
1011
1012 assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1013 }
1014
1015 assert((1 << mem_type_index) & mem_type_bits);
1016
1017 errno = 0;
1018 dup_fd = os_dupfd_cloexec(dma_buf_fd);
1019 if (dup_fd < 0)
1020 return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1021 : VK_ERROR_OUT_OF_HOST_MEMORY;
1022
1023 /* Spec requires AHB export info to be present, so we must strip it. In
1024 * practice, the AHB import path here only needs the main allocation info
1025 * and the dedicated_info.
1026 */
1027 VkMemoryDedicatedAllocateInfo local_dedicated_info;
1028 /* Override when dedicated_info exists and is not the tail struct. */
1029 if (dedicated_info && dedicated_info->pNext) {
1030 local_dedicated_info = *dedicated_info;
1031 local_dedicated_info.pNext = NULL;
1032 dedicated_info = &local_dedicated_info;
1033 }
1034 const VkMemoryAllocateInfo local_alloc_info = {
1035 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1036 .pNext = dedicated_info,
1037 .allocationSize = alloc_size,
1038 .memoryTypeIndex = mem_type_index,
1039 };
1040 result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1041 force_unmappable, dup_fd);
1042 if (result != VK_SUCCESS) {
1043 close(dup_fd);
1044 return result;
1045 }
1046
1047 return VK_SUCCESS;
1048 }
1049
1050 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1051 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1052 {
1053 static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1054 /* ensure dma_buf_memory_type_bits covers host visible usage */
1055 static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1056 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1057 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1058 AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1059 if (!ahb)
1060 return 0;
1061
1062 int dma_buf_fd =
1063 vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1064 if (dma_buf_fd < 0) {
1065 AHardwareBuffer_release(ahb);
1066 return 0;
1067 }
1068
1069 uint64_t alloc_size = 0;
1070 uint32_t mem_type_bits = 0;
1071 VkResult ret = vn_get_memory_dma_buf_properties(
1072 dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1073 /* release ahb first as below no longer needs it */
1074 AHardwareBuffer_release(ahb);
1075
1076 if (ret != VK_SUCCESS) {
1077 vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1078 return 0;
1079 }
1080
1081 return mem_type_bits;
1082 }
1083