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,const VkAllocationCallbacks * alloc,VkDrmFormatModifierPropertiesEXT * out_props)351 vn_android_get_modifier_properties(struct vn_device *dev,
352 VkFormat format,
353 uint64_t modifier,
354 const VkAllocationCallbacks *alloc,
355 VkDrmFormatModifierPropertiesEXT *out_props)
356 {
357 VkPhysicalDevice physical_device =
358 vn_physical_device_to_handle(dev->physical_device);
359 VkDrmFormatModifierPropertiesListEXT mod_prop_list = {
360 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
361 .pNext = NULL,
362 .drmFormatModifierCount = 0,
363 .pDrmFormatModifierProperties = NULL,
364 };
365 VkFormatProperties2 format_prop = {
366 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
367 .pNext = &mod_prop_list,
368 };
369 VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
370 bool modifier_found = false;
371
372 vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
373 &format_prop);
374
375 if (!mod_prop_list.drmFormatModifierCount) {
376 vn_log(dev->instance, "No compatible modifier for VkFormat(%u)",
377 format);
378 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
379 }
380
381 mod_props = vk_zalloc(
382 alloc, sizeof(*mod_props) * mod_prop_list.drmFormatModifierCount,
383 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
384 if (!mod_props)
385 return VK_ERROR_OUT_OF_HOST_MEMORY;
386
387 mod_prop_list.pDrmFormatModifierProperties = mod_props;
388 vn_GetPhysicalDeviceFormatProperties2(physical_device, format,
389 &format_prop);
390
391 for (uint32_t i = 0; i < mod_prop_list.drmFormatModifierCount; i++) {
392 if (mod_props[i].drmFormatModifier == modifier) {
393 *out_props = mod_props[i];
394 modifier_found = true;
395 break;
396 }
397 }
398
399 vk_free(alloc, mod_props);
400
401 if (!modifier_found) {
402 vn_log(dev->instance,
403 "No matching modifier(%" PRIu64 ") properties for VkFormat(%u)",
404 modifier, format);
405 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
406 }
407
408 return VK_SUCCESS;
409 }
410
411 struct vn_android_image_builder {
412 VkImageCreateInfo create;
413 VkSubresourceLayout layouts[4];
414 VkImageDrmFormatModifierExplicitCreateInfoEXT modifier;
415 VkExternalMemoryImageCreateInfo external;
416 VkImageFormatListCreateInfo list;
417 };
418
419 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)420 vn_android_get_image_builder(struct vn_device *dev,
421 const VkImageCreateInfo *create_info,
422 const native_handle_t *handle,
423 struct vn_android_image_builder *out_builder)
424 {
425 /* Android image builder is only used by ANB or AHB. For ANB, Android
426 * Vulkan loader will never pass the below structs. For AHB, struct
427 * vn_image_create_deferred_info will never carry below either.
428 */
429 assert(!vk_find_struct_const(
430 create_info->pNext,
431 IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT));
432 assert(!vk_find_struct_const(create_info->pNext,
433 EXTERNAL_MEMORY_IMAGE_CREATE_INFO));
434
435 struct vn_android_gralloc_buffer_properties buf_props;
436 if (!vn_android_gralloc_get_buffer_properties(handle, &buf_props))
437 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
438
439 /* fill VkImageCreateInfo */
440 memset(out_builder, 0, sizeof(*out_builder));
441 out_builder->create = *create_info;
442 out_builder->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
443
444 /* fill VkImageDrmFormatModifierExplicitCreateInfoEXT */
445 for (uint32_t i = 0; i < buf_props.num_planes; i++) {
446 out_builder->layouts[i].offset = buf_props.offset[i];
447 out_builder->layouts[i].rowPitch = buf_props.stride[i];
448 }
449 out_builder->modifier = (VkImageDrmFormatModifierExplicitCreateInfoEXT){
450 .sType =
451 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
452 .pNext = out_builder->create.pNext,
453 .drmFormatModifier = buf_props.modifier,
454 .drmFormatModifierPlaneCount = buf_props.num_planes,
455 .pPlaneLayouts = out_builder->layouts,
456 };
457 out_builder->create.pNext = &out_builder->modifier;
458
459 /* fill VkExternalMemoryImageCreateInfo */
460 out_builder->external = (VkExternalMemoryImageCreateInfo){
461 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
462 .pNext = out_builder->create.pNext,
463 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
464 };
465 out_builder->create.pNext = &out_builder->external;
466
467 /* fill VkImageFormatListCreateInfo if needed
468 *
469 * vn_image::deferred_info only stores VkImageFormatListCreateInfo with a
470 * non-zero viewFormatCount, and that stored struct will be respected.
471 */
472 if ((create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
473 !vk_find_struct_const(create_info->pNext,
474 IMAGE_FORMAT_LIST_CREATE_INFO)) {
475 /* 12.3. Images
476 *
477 * If tiling is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT and flags
478 * contains VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, then the pNext chain
479 * must include a VkImageFormatListCreateInfo structure with non-zero
480 * viewFormatCount.
481 */
482 uint32_t vcount = 0;
483 const VkFormat *vformats =
484 vn_android_format_to_view_formats(create_info->format, &vcount);
485 if (!vformats) {
486 /* image builder struct persists through the image creation call */
487 vformats = &out_builder->create.format;
488 vcount = 1;
489 }
490 out_builder->list = (VkImageFormatListCreateInfo){
491 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
492 .pNext = out_builder->create.pNext,
493 .viewFormatCount = vcount,
494 .pViewFormats = vformats,
495 };
496 out_builder->create.pNext = &out_builder->list;
497 }
498
499 return VK_SUCCESS;
500 }
501
502 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)503 vn_android_image_from_anb(struct vn_device *dev,
504 const VkImageCreateInfo *create_info,
505 const VkNativeBufferANDROID *anb_info,
506 const VkAllocationCallbacks *alloc,
507 struct vn_image **out_img)
508 {
509 /* If anb_info->handle points to a classic resouce created from
510 * virtio_gpu_cmd_resource_create_3d, anb_info->stride is the stride of the
511 * guest shadow storage other than the host gpu storage.
512 *
513 * We also need to pass the correct stride to vn_CreateImage, which will be
514 * done via VkImageDrmFormatModifierExplicitCreateInfoEXT and will require
515 * VK_EXT_image_drm_format_modifier support in the host driver. The struct
516 * needs host storage info which can be queried from cros gralloc.
517 */
518 VkResult result = VK_SUCCESS;
519 VkDevice device = vn_device_to_handle(dev);
520 VkDeviceMemory memory = VK_NULL_HANDLE;
521 VkImage image = VK_NULL_HANDLE;
522 struct vn_image *img = NULL;
523 uint64_t alloc_size = 0;
524 uint32_t mem_type_bits = 0;
525 int dma_buf_fd = -1;
526 int dup_fd = -1;
527 VkImageCreateInfo local_create_info;
528 struct vn_android_image_builder builder;
529
530 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(anb_info->handle);
531 if (dma_buf_fd < 0) {
532 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
533 goto fail;
534 }
535
536 assert(!(create_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT));
537 assert(!vk_find_struct_const(create_info->pNext,
538 IMAGE_FORMAT_LIST_CREATE_INFO));
539 assert(!vk_find_struct_const(create_info->pNext,
540 IMAGE_STENCIL_USAGE_CREATE_INFO));
541
542 /* strip VkNativeBufferANDROID and VkSwapchainImageCreateInfoANDROID */
543 local_create_info = *create_info;
544 local_create_info.pNext = NULL;
545 result = vn_android_get_image_builder(dev, &local_create_info,
546 anb_info->handle, &builder);
547 if (result != VK_SUCCESS)
548 goto fail;
549
550 /* encoder will strip the Android specific pNext structs */
551 result = vn_image_create(dev, &builder.create, alloc, &img);
552 if (result != VK_SUCCESS) {
553 if (VN_DEBUG(WSI))
554 vn_log(dev->instance, "vn_image_create failed");
555 goto fail;
556 }
557
558 image = vn_image_to_handle(img);
559
560 const VkMemoryRequirements *mem_req =
561 &img->requirements[0].memory.memoryRequirements;
562 if (!mem_req->memoryTypeBits) {
563 if (VN_DEBUG(WSI))
564 vn_log(dev->instance, "mem_req->memoryTypeBits cannot be zero");
565 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
566 goto fail;
567 }
568
569 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
570 &mem_type_bits);
571 if (result != VK_SUCCESS)
572 goto fail;
573
574 if (VN_DEBUG(WSI)) {
575 vn_log(dev->instance,
576 "size = img(%" PRIu64 ") fd(%" PRIu64 "), "
577 "memoryTypeBits = img(0x%X) & fd(0x%X)",
578 mem_req->size, alloc_size, mem_req->memoryTypeBits,
579 mem_type_bits);
580 }
581
582 if (alloc_size < mem_req->size) {
583 if (VN_DEBUG(WSI)) {
584 vn_log(dev->instance,
585 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
586 alloc_size, mem_req->size);
587 }
588 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
589 goto fail;
590 }
591
592 mem_type_bits &= mem_req->memoryTypeBits;
593 if (!mem_type_bits) {
594 result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
595 goto fail;
596 }
597
598 dup_fd = os_dupfd_cloexec(dma_buf_fd);
599 if (dup_fd < 0) {
600 result = (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
601 : VK_ERROR_OUT_OF_HOST_MEMORY;
602 goto fail;
603 }
604
605 const VkImportMemoryFdInfoKHR import_fd_info = {
606 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
607 .pNext = NULL,
608 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
609 .fd = dup_fd,
610 };
611 const VkMemoryAllocateInfo memory_info = {
612 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
613 .pNext = &import_fd_info,
614 .allocationSize = mem_req->size,
615 .memoryTypeIndex = ffs(mem_type_bits) - 1,
616 };
617 result = vn_AllocateMemory(device, &memory_info, alloc, &memory);
618 if (result != VK_SUCCESS) {
619 /* only need to close the dup_fd on import failure */
620 close(dup_fd);
621 goto fail;
622 }
623
624 const VkBindImageMemoryInfo bind_info = {
625 .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
626 .pNext = NULL,
627 .image = image,
628 .memory = memory,
629 .memoryOffset = 0,
630 };
631 result = vn_BindImageMemory2(device, 1, &bind_info);
632 if (result != VK_SUCCESS)
633 goto fail;
634
635 img->wsi.is_wsi = true;
636 img->wsi.tiling_override = builder.create.tiling;
637 img->wsi.drm_format_modifier = builder.modifier.drmFormatModifier;
638 /* Android WSI image owns the memory */
639 img->wsi.memory = vn_device_memory_from_handle(memory);
640 img->wsi.memory_owned = true;
641 *out_img = img;
642
643 return VK_SUCCESS;
644
645 fail:
646 if (image != VK_NULL_HANDLE)
647 vn_DestroyImage(device, image, alloc);
648 if (memory != VK_NULL_HANDLE)
649 vn_FreeMemory(device, memory, alloc);
650 return vn_error(dev->instance, result);
651 }
652
653 static VkResult
vn_android_get_ahb_format_properties(struct vn_device * dev,const struct AHardwareBuffer * ahb,VkAndroidHardwareBufferFormatPropertiesANDROID * out_props)654 vn_android_get_ahb_format_properties(
655 struct vn_device *dev,
656 const struct AHardwareBuffer *ahb,
657 VkAndroidHardwareBufferFormatPropertiesANDROID *out_props)
658 {
659 AHardwareBuffer_Desc desc;
660 VkFormat format;
661 struct vn_android_gralloc_buffer_properties buf_props;
662 VkDrmFormatModifierPropertiesEXT mod_props;
663
664 AHardwareBuffer_describe(ahb, &desc);
665 if (!(desc.usage & (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
666 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
667 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
668 vn_log(dev->instance,
669 "AHB usage(%" PRIu64 ") must include at least one GPU bit",
670 desc.usage);
671 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
672 }
673
674 /* Handle the special AHARDWAREBUFFER_FORMAT_BLOB for VkBuffer case. */
675 if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
676 out_props->format = VK_FORMAT_UNDEFINED;
677 return VK_SUCCESS;
678 }
679
680 if (!vn_android_gralloc_get_buffer_properties(
681 AHardwareBuffer_getNativeHandle(ahb), &buf_props))
682 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
683
684 /* We implement AHB extension support with EXT_image_drm_format_modifier.
685 * It requires us to have a compatible VkFormat but not DRM formats. So if
686 * the ahb is not intended for backing a VkBuffer, error out early if the
687 * format is VK_FORMAT_UNDEFINED.
688 */
689 format = vn_android_drm_format_to_vk_format(buf_props.drm_fourcc);
690 if (format == VK_FORMAT_UNDEFINED) {
691 vn_log(dev->instance, "Unknown drm_fourcc(%u) from AHB format(0x%X)",
692 buf_props.drm_fourcc, desc.format);
693 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
694 }
695
696 VkResult result = vn_android_get_modifier_properties(
697 dev, format, buf_props.modifier, &dev->base.base.alloc, &mod_props);
698 if (result != VK_SUCCESS)
699 return result;
700
701 if (mod_props.drmFormatModifierPlaneCount != buf_props.num_planes) {
702 vn_log(dev->instance,
703 "drmFormatModifierPlaneCount(%u) != buf_props.num_planes(%u) "
704 "for DRM format modifier(%" PRIu64 ")",
705 mod_props.drmFormatModifierPlaneCount, buf_props.num_planes,
706 buf_props.modifier);
707 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
708 }
709
710 /* The spec requires that formatFeatures must include at least one of
711 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
712 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT.
713 */
714 const VkFormatFeatureFlags format_features =
715 mod_props.drmFormatModifierTilingFeatures |
716 VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
717
718 /* 11.2.7. Android Hardware Buffer External Memory
719 *
720 * Implementations may not always be able to determine the color model,
721 * numerical range, or chroma offsets of the image contents, so the values
722 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
723 * Applications should treat these values as sensible defaults to use in the
724 * absence of more reliable information obtained through some other means.
725 */
726 const bool is_yuv = vn_android_drm_format_is_yuv(buf_props.drm_fourcc);
727 const VkSamplerYcbcrModelConversion model =
728 is_yuv ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
729 : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
730
731 /* ANGLE expects VK_FORMAT_UNDEFINED with externalFormat resolved from
732 * AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED and any supported planar
733 * AHB formats. Venus supports below explicit ones:
734 * - AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 (DRM_FORMAT_NV12)
735 * - AHARDWAREBUFFER_FORMAT_YV12 (DRM_FORMAT_YVU420)
736 */
737 if (desc.format == AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED || is_yuv)
738 format = VK_FORMAT_UNDEFINED;
739
740 *out_props = (VkAndroidHardwareBufferFormatPropertiesANDROID) {
741 .sType = out_props->sType,
742 .pNext = out_props->pNext,
743 .format = format,
744 .externalFormat = buf_props.drm_fourcc,
745 .formatFeatures = format_features,
746 .samplerYcbcrConversionComponents = {
747 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
748 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
749 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
750 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
751 },
752 .suggestedYcbcrModel = model,
753 /* match EGL_YUV_NARROW_RANGE_EXT used in egl platform_android */
754 .suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
755 .suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
756 .suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
757 };
758
759 return VK_SUCCESS;
760 }
761
762 VkResult
vn_GetAndroidHardwareBufferPropertiesANDROID(VkDevice device,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)763 vn_GetAndroidHardwareBufferPropertiesANDROID(
764 VkDevice device,
765 const struct AHardwareBuffer *buffer,
766 VkAndroidHardwareBufferPropertiesANDROID *pProperties)
767 {
768 VN_TRACE_FUNC();
769 struct vn_device *dev = vn_device_from_handle(device);
770 VkResult result = VK_SUCCESS;
771 int dma_buf_fd = -1;
772 uint64_t alloc_size = 0;
773 uint32_t mem_type_bits = 0;
774
775 VkAndroidHardwareBufferFormatProperties2ANDROID *format_props2 =
776 vk_find_struct(pProperties->pNext,
777 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID);
778 VkAndroidHardwareBufferFormatPropertiesANDROID *format_props =
779 vk_find_struct(pProperties->pNext,
780 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
781 if (format_props2 || format_props) {
782 VkAndroidHardwareBufferFormatPropertiesANDROID local_props = {
783 .sType =
784 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
785 };
786 if (!format_props)
787 format_props = &local_props;
788
789 result =
790 vn_android_get_ahb_format_properties(dev, buffer, format_props);
791 if (result != VK_SUCCESS)
792 return vn_error(dev->instance, result);
793
794 if (format_props2) {
795 format_props2->format = format_props->format;
796 format_props2->externalFormat = format_props->externalFormat;
797 format_props2->formatFeatures =
798 (VkFormatFeatureFlags2)format_props->formatFeatures;
799 format_props2->samplerYcbcrConversionComponents =
800 format_props->samplerYcbcrConversionComponents;
801 format_props2->suggestedYcbcrModel =
802 format_props->suggestedYcbcrModel;
803 format_props2->suggestedYcbcrRange =
804 format_props->suggestedYcbcrRange;
805 format_props2->suggestedXChromaOffset =
806 format_props->suggestedXChromaOffset;
807 format_props2->suggestedYChromaOffset =
808 format_props->suggestedYChromaOffset;
809 }
810 }
811
812 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(
813 AHardwareBuffer_getNativeHandle(buffer));
814 if (dma_buf_fd < 0)
815 return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
816
817 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
818 &mem_type_bits);
819 if (result != VK_SUCCESS)
820 return vn_error(dev->instance, result);
821
822 pProperties->allocationSize = alloc_size;
823 pProperties->memoryTypeBits = mem_type_bits;
824
825 return VK_SUCCESS;
826 }
827
828 static AHardwareBuffer *
vn_android_ahb_allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)829 vn_android_ahb_allocate(uint32_t width,
830 uint32_t height,
831 uint32_t layers,
832 uint32_t format,
833 uint64_t usage)
834 {
835 AHardwareBuffer *ahb = NULL;
836 AHardwareBuffer_Desc desc;
837 int ret = 0;
838
839 memset(&desc, 0, sizeof(desc));
840 desc.width = width;
841 desc.height = height;
842 desc.layers = layers;
843 desc.format = format;
844 desc.usage = usage;
845
846 ret = AHardwareBuffer_allocate(&desc, &ahb);
847 if (ret) {
848 /* We just log the error code here for now since the platform falsely
849 * maps all gralloc allocation failures to oom.
850 */
851 vn_log(NULL, "AHB alloc(w=%u,h=%u,l=%u,f=%u,u=%" PRIu64 ") failed(%d)",
852 width, height, layers, format, usage, ret);
853 return NULL;
854 }
855
856 return ahb;
857 }
858
859 bool
vn_android_get_drm_format_modifier_info(const VkPhysicalDeviceImageFormatInfo2 * format_info,VkPhysicalDeviceImageDrmFormatModifierInfoEXT * out_info)860 vn_android_get_drm_format_modifier_info(
861 const VkPhysicalDeviceImageFormatInfo2 *format_info,
862 VkPhysicalDeviceImageDrmFormatModifierInfoEXT *out_info)
863 {
864 /* To properly fill VkPhysicalDeviceImageDrmFormatModifierInfoEXT, we have
865 * to allocate an ahb to retrieve the drm format modifier. For the image
866 * sharing mode, we assume VK_SHARING_MODE_EXCLUSIVE for now.
867 */
868 AHardwareBuffer *ahb = NULL;
869 uint32_t format = 0;
870 uint64_t usage = 0;
871 struct vn_android_gralloc_buffer_properties buf_props;
872
873 assert(format_info->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
874
875 format = vk_image_format_to_ahb_format(format_info->format);
876 if (!format)
877 return false;
878
879 usage =
880 vk_image_usage_to_ahb_usage(format_info->flags, format_info->usage);
881 ahb = vn_android_ahb_allocate(16, 16, 1, format, usage);
882 if (!ahb)
883 return false;
884
885 if (!vn_android_gralloc_get_buffer_properties(
886 AHardwareBuffer_getNativeHandle(ahb), &buf_props)) {
887 AHardwareBuffer_release(ahb);
888 return false;
889 }
890
891 *out_info = (VkPhysicalDeviceImageDrmFormatModifierInfoEXT){
892 .sType =
893 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
894 .pNext = NULL,
895 .drmFormatModifier = buf_props.modifier,
896 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
897 .queueFamilyIndexCount = 0,
898 .pQueueFamilyIndices = NULL,
899 };
900
901 AHardwareBuffer_release(ahb);
902 return true;
903 }
904
905 VkResult
vn_android_device_import_ahb(struct vn_device * dev,struct vn_device_memory * mem,const struct VkMemoryDedicatedAllocateInfo * dedicated_info)906 vn_android_device_import_ahb(
907 struct vn_device *dev,
908 struct vn_device_memory *mem,
909 const struct VkMemoryDedicatedAllocateInfo *dedicated_info)
910 {
911 const struct vk_device_memory *mem_vk = &mem->base.base;
912 const native_handle_t *handle = NULL;
913 int dma_buf_fd = -1;
914 int dup_fd = -1;
915 uint64_t alloc_size = 0;
916 uint32_t mem_type_bits = 0;
917 uint32_t mem_type_index = mem_vk->memory_type_index;
918 bool force_unmappable = false;
919 VkResult result = VK_SUCCESS;
920
921 handle = AHardwareBuffer_getNativeHandle(mem_vk->ahardware_buffer);
922 dma_buf_fd = vn_android_gralloc_get_dma_buf_fd(handle);
923 if (dma_buf_fd < 0)
924 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
925
926 result = vn_get_memory_dma_buf_properties(dev, dma_buf_fd, &alloc_size,
927 &mem_type_bits);
928 if (result != VK_SUCCESS)
929 return result;
930
931 /* If ahb is for an image, finish the deferred image creation first */
932 if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
933 struct vn_image *img = vn_image_from_handle(dedicated_info->image);
934 struct vn_android_image_builder builder;
935
936 result = vn_android_get_image_builder(dev, &img->deferred_info->create,
937 handle, &builder);
938 if (result != VK_SUCCESS)
939 return result;
940
941 result = vn_image_init_deferred(dev, &builder.create, img);
942 if (result != VK_SUCCESS)
943 return result;
944
945 const VkMemoryRequirements *mem_req =
946 &img->requirements[0].memory.memoryRequirements;
947 if (alloc_size < mem_req->size) {
948 vn_log(dev->instance,
949 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
950 alloc_size, mem_req->size);
951 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
952 }
953
954 alloc_size = mem_req->size;
955
956 /* Per spec 11.2.3. Device Memory Allocation
957 *
958 * If the parameters define an export operation and the external handle
959 * type is
960 * VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
961 * implementations should not strictly follow memoryTypeIndex. Instead,
962 * they should modify the allocation internally to use the required
963 * memory type for the application’s given usage. This is because for an
964 * export operation, there is currently no way for the client to know
965 * the memory type index before allocating.
966 */
967 if (!(mem_vk->import_handle_type &
968 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)) {
969 if ((mem_type_bits & mem_req->memoryTypeBits) == 0) {
970 vn_log(dev->instance, "memoryTypeBits: img(0x%X) fd(0x%X)",
971 mem_req->memoryTypeBits, mem_type_bits);
972 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
973 }
974
975 mem_type_index = ffs(mem_type_bits & mem_req->memoryTypeBits) - 1;
976 }
977
978 /* XXX Workaround before we use cross-domain backend in minigbm. The
979 * blob_mem allocated from virgl backend can have a queried guest
980 * mappable size smaller than the size returned from image memory
981 * requirement.
982 */
983 force_unmappable = true;
984 }
985
986 if (dedicated_info && dedicated_info->buffer != VK_NULL_HANDLE) {
987 struct vn_buffer *buf = vn_buffer_from_handle(dedicated_info->buffer);
988 const VkMemoryRequirements *mem_req =
989 &buf->requirements.memory.memoryRequirements;
990 if (alloc_size < mem_req->size) {
991 vn_log(dev->instance,
992 "alloc_size(%" PRIu64 ") mem_req->size(%" PRIu64 ")",
993 alloc_size, mem_req->size);
994 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
995 }
996
997 alloc_size = mem_req->size;
998
999 assert((1 << mem_type_index) & mem_req->memoryTypeBits);
1000 }
1001
1002 assert((1 << mem_type_index) & mem_type_bits);
1003
1004 errno = 0;
1005 dup_fd = os_dupfd_cloexec(dma_buf_fd);
1006 if (dup_fd < 0)
1007 return (errno == EMFILE) ? VK_ERROR_TOO_MANY_OBJECTS
1008 : VK_ERROR_OUT_OF_HOST_MEMORY;
1009
1010 /* Spec requires AHB export info to be present, so we must strip it. In
1011 * practice, the AHB import path here only needs the main allocation info
1012 * and the dedicated_info.
1013 */
1014 VkMemoryDedicatedAllocateInfo local_dedicated_info;
1015 /* Override when dedicated_info exists and is not the tail struct. */
1016 if (dedicated_info && dedicated_info->pNext) {
1017 local_dedicated_info = *dedicated_info;
1018 local_dedicated_info.pNext = NULL;
1019 dedicated_info = &local_dedicated_info;
1020 }
1021 const VkMemoryAllocateInfo local_alloc_info = {
1022 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1023 .pNext = dedicated_info,
1024 .allocationSize = alloc_size,
1025 .memoryTypeIndex = mem_type_index,
1026 };
1027 result = vn_device_memory_import_dma_buf(dev, mem, &local_alloc_info,
1028 force_unmappable, dup_fd);
1029 if (result != VK_SUCCESS) {
1030 close(dup_fd);
1031 return result;
1032 }
1033
1034 return VK_SUCCESS;
1035 }
1036
1037 uint32_t
vn_android_get_ahb_buffer_memory_type_bits(struct vn_device * dev)1038 vn_android_get_ahb_buffer_memory_type_bits(struct vn_device *dev)
1039 {
1040 static const uint32_t format = AHARDWAREBUFFER_FORMAT_BLOB;
1041 /* ensure dma_buf_memory_type_bits covers host visible usage */
1042 static const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
1043 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
1044 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1045 AHardwareBuffer *ahb = vn_android_ahb_allocate(4096, 1, 1, format, usage);
1046 if (!ahb)
1047 return 0;
1048
1049 int dma_buf_fd =
1050 vn_android_gralloc_get_dma_buf_fd(AHardwareBuffer_getNativeHandle(ahb));
1051 if (dma_buf_fd < 0) {
1052 AHardwareBuffer_release(ahb);
1053 return 0;
1054 }
1055
1056 uint64_t alloc_size = 0;
1057 uint32_t mem_type_bits = 0;
1058 VkResult ret = vn_get_memory_dma_buf_properties(
1059 dev, dma_buf_fd, &alloc_size, &mem_type_bits);
1060 /* release ahb first as below no longer needs it */
1061 AHardwareBuffer_release(ahb);
1062
1063 if (ret != VK_SUCCESS) {
1064 vn_log(dev->instance, "AHB buffer mem type bits query failed %d", ret);
1065 return 0;
1066 }
1067
1068 return mem_type_bits;
1069 }
1070