radv: replace all dup() with os_dupfd_cloexec()
[mesa.git] / src / amd / vulkan / radv_android.c
1 /*
2 * Copyright © 2017, Google Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifdef ANDROID
25 #include <hardware/gralloc.h>
26 #include <hardware/hardware.h>
27 #include <hardware/hwvulkan.h>
28 #include <vndk/hardware_buffer.h>
29 #include <vulkan/vk_android_native_buffer.h>
30 #include <vulkan/vk_icd.h>
31 #include <libsync.h>
32
33 #if ANDROID_API_LEVEL >= 26
34 #include <hardware/gralloc1.h>
35 #endif
36 #endif
37
38 #include "util/os_file.h"
39
40 #include "radv_private.h"
41 #include "vk_util.h"
42
43 #ifdef ANDROID
44
45 static int radv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev);
46 static int radv_hal_close(struct hw_device_t *dev);
47
48 static void UNUSED
49 static_asserts(void)
50 {
51 STATIC_ASSERT(HWVULKAN_DISPATCH_MAGIC == ICD_LOADER_MAGIC);
52 }
53
54 PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {
55 .common = {
56 .tag = HARDWARE_MODULE_TAG,
57 .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
58 .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),
59 .id = HWVULKAN_HARDWARE_MODULE_ID,
60 .name = "AMD Vulkan HAL",
61 .author = "Google",
62 .methods = &(hw_module_methods_t) {
63 .open = radv_hal_open,
64 },
65 },
66 };
67
68 /* If any bits in test_mask are set, then unset them and return true. */
69 static inline bool
70 unmask32(uint32_t *inout_mask, uint32_t test_mask)
71 {
72 uint32_t orig_mask = *inout_mask;
73 *inout_mask &= ~test_mask;
74 return *inout_mask != orig_mask;
75 }
76
77 static int
78 radv_hal_open(const struct hw_module_t* mod, const char* id,
79 struct hw_device_t** dev)
80 {
81 assert(mod == &HAL_MODULE_INFO_SYM.common);
82 assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);
83
84 hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));
85 if (!hal_dev)
86 return -1;
87
88 *hal_dev = (hwvulkan_device_t) {
89 .common = {
90 .tag = HARDWARE_DEVICE_TAG,
91 .version = HWVULKAN_DEVICE_API_VERSION_0_1,
92 .module = &HAL_MODULE_INFO_SYM.common,
93 .close = radv_hal_close,
94 },
95 .EnumerateInstanceExtensionProperties = radv_EnumerateInstanceExtensionProperties,
96 .CreateInstance = radv_CreateInstance,
97 .GetInstanceProcAddr = radv_GetInstanceProcAddr,
98 };
99
100 *dev = &hal_dev->common;
101 return 0;
102 }
103
104 static int
105 radv_hal_close(struct hw_device_t *dev)
106 {
107 /* hwvulkan.h claims that hw_device_t::close() is never called. */
108 return -1;
109 }
110
111 VkResult
112 radv_image_from_gralloc(VkDevice device_h,
113 const VkImageCreateInfo *base_info,
114 const VkNativeBufferANDROID *gralloc_info,
115 const VkAllocationCallbacks *alloc,
116 VkImage *out_image_h)
117
118 {
119 RADV_FROM_HANDLE(radv_device, device, device_h);
120 VkImage image_h = VK_NULL_HANDLE;
121 struct radv_image *image = NULL;
122 struct radv_bo *bo = NULL;
123 VkResult result;
124
125 if (gralloc_info->handle->numFds != 1) {
126 return vk_errorf(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE,
127 "VkNativeBufferANDROID::handle::numFds is %d, "
128 "expected 1", gralloc_info->handle->numFds);
129 }
130
131 /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf
132 * must exceed that of the gralloc handle, and we do not own the gralloc
133 * handle.
134 */
135 int dma_buf = gralloc_info->handle->data[0];
136
137 VkDeviceMemory memory_h;
138
139 const VkImportMemoryFdInfoKHR import_info = {
140 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
141 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
142 .fd = os_dupfd_cloexec(dma_buf),
143 };
144
145 /* Find the first VRAM memory type, or GART for PRIME images. */
146 int memory_type_index = -1;
147 for (int i = 0; i < device->physical_device->memory_properties.memoryTypeCount; ++i) {
148 bool is_local = !!(device->physical_device->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
149 if (is_local) {
150 memory_type_index = i;
151 break;
152 }
153 }
154
155 /* fallback */
156 if (memory_type_index == -1)
157 memory_type_index = 0;
158
159 result = radv_AllocateMemory(device_h,
160 &(VkMemoryAllocateInfo) {
161 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
162 .pNext = &import_info,
163 /* Max buffer size, unused for imports */
164 .allocationSize = 0x7FFFFFFF,
165 .memoryTypeIndex = memory_type_index,
166 },
167 alloc,
168 &memory_h);
169 if (result != VK_SUCCESS)
170 return result;
171
172 struct radeon_bo_metadata md;
173 device->ws->buffer_get_metadata(radv_device_memory_from_handle(memory_h)->bo, &md);
174
175 VkImageCreateInfo updated_base_info = *base_info;
176
177 VkExternalMemoryImageCreateInfo external_memory_info = {
178 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
179 .pNext = updated_base_info.pNext,
180 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
181 };
182
183 updated_base_info.pNext = &external_memory_info;
184
185 result = radv_image_create(device_h,
186 &(struct radv_image_create_info) {
187 .vk_info = &updated_base_info,
188 .no_metadata_planes = true,
189 .bo_metadata = &md,
190 },
191 alloc,
192 &image_h);
193
194 if (result != VK_SUCCESS)
195 goto fail_create_image;
196
197 image = radv_image_from_handle(image_h);
198
199 radv_image_override_offset_stride(device, image, 0, gralloc_info->stride);
200
201 radv_BindImageMemory(device_h, image_h, memory_h, 0);
202
203 image->owned_memory = memory_h;
204 /* Don't clobber the out-parameter until success is certain. */
205 *out_image_h = image_h;
206
207 return VK_SUCCESS;
208
209 fail_create_image:
210 radv_FreeMemory(device_h, memory_h, alloc);
211 return result;
212 }
213
214 VkResult radv_GetSwapchainGrallocUsageANDROID(
215 VkDevice device_h,
216 VkFormat format,
217 VkImageUsageFlags imageUsage,
218 int* grallocUsage)
219 {
220 RADV_FROM_HANDLE(radv_device, device, device_h);
221 struct radv_physical_device *phys_dev = device->physical_device;
222 VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
223 VkResult result;
224
225 *grallocUsage = 0;
226
227 /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags
228 * returned to applications via VkSurfaceCapabilitiesKHR::supportedUsageFlags.
229 * The relevant code in libvulkan/swapchain.cpp contains this fun comment:
230 *
231 * TODO(jessehall): I think these are right, but haven't thought hard
232 * about it. Do we need to query the driver for support of any of
233 * these?
234 *
235 * Any disagreement between this function and the hardcoded
236 * VkSurfaceCapabilitiesKHR:supportedUsageFlags causes tests
237 * dEQP-VK.wsi.android.swapchain.*.image_usage to fail.
238 */
239
240 const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
241 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
242 .format = format,
243 .type = VK_IMAGE_TYPE_2D,
244 .tiling = VK_IMAGE_TILING_OPTIMAL,
245 .usage = imageUsage,
246 };
247
248 VkImageFormatProperties2 image_format_props = {
249 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
250 };
251
252 /* Check that requested format and usage are supported. */
253 result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h,
254 &image_format_info, &image_format_props);
255 if (result != VK_SUCCESS) {
256 return vk_errorf(device->instance, result,
257 "radv_GetPhysicalDeviceImageFormatProperties2 failed "
258 "inside %s", __func__);
259 }
260
261 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
262 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
263 *grallocUsage |= GRALLOC_USAGE_HW_RENDER;
264
265 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
266 VK_IMAGE_USAGE_SAMPLED_BIT |
267 VK_IMAGE_USAGE_STORAGE_BIT |
268 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
269 *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;
270
271 /* All VkImageUsageFlags not explicitly checked here are unsupported for
272 * gralloc swapchains.
273 */
274 if (imageUsage != 0) {
275 return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
276 "unsupported VkImageUsageFlags(0x%x) for gralloc "
277 "swapchain", imageUsage);
278 }
279
280 /*
281 * FINISHME: Advertise all display-supported formats. Mostly
282 * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
283 * what we need for 30-bit colors.
284 */
285 if (format == VK_FORMAT_B8G8R8A8_UNORM ||
286 format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
287 *grallocUsage |= GRALLOC_USAGE_HW_FB |
288 GRALLOC_USAGE_HW_COMPOSER |
289 GRALLOC_USAGE_EXTERNAL_DISP;
290 }
291
292 if (*grallocUsage == 0)
293 return VK_ERROR_FORMAT_NOT_SUPPORTED;
294
295 return VK_SUCCESS;
296 }
297
298 VkResult radv_GetSwapchainGrallocUsage2ANDROID(
299 VkDevice device_h,
300 VkFormat format,
301 VkImageUsageFlags imageUsage,
302 VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
303 uint64_t* grallocConsumerUsage,
304 uint64_t* grallocProducerUsage)
305 {
306 /* Before level 26 (Android 8.0/Oreo) the loader uses
307 * vkGetSwapchainGrallocUsageANDROID. */
308 #if ANDROID_API_LEVEL >= 26
309 RADV_FROM_HANDLE(radv_device, device, device_h);
310 struct radv_physical_device *phys_dev = device->physical_device;
311 VkPhysicalDevice phys_dev_h = radv_physical_device_to_handle(phys_dev);
312 VkResult result;
313
314 *grallocConsumerUsage = 0;
315 *grallocProducerUsage = 0;
316
317 if (swapchainImageUsage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)
318 return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
319 "The Vulkan loader tried to query shared presentable image support");
320
321 const VkPhysicalDeviceImageFormatInfo2 image_format_info = {
322 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
323 .format = format,
324 .type = VK_IMAGE_TYPE_2D,
325 .tiling = VK_IMAGE_TILING_OPTIMAL,
326 .usage = imageUsage,
327 };
328
329 VkImageFormatProperties2 image_format_props = {
330 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
331 };
332
333 /* Check that requested format and usage are supported. */
334 result = radv_GetPhysicalDeviceImageFormatProperties2(phys_dev_h,
335 &image_format_info, &image_format_props);
336 if (result != VK_SUCCESS) {
337 return vk_errorf(device->instance, result,
338 "radv_GetPhysicalDeviceImageFormatProperties2 failed "
339 "inside %s", __func__);
340 }
341
342 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BIT |
343 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
344 *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
345 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET;
346 }
347
348 if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
349 VK_IMAGE_USAGE_SAMPLED_BIT |
350 VK_IMAGE_USAGE_STORAGE_BIT |
351 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
352 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
353 }
354
355 if (imageUsage != 0) {
356 return vk_errorf(device->instance, VK_ERROR_FORMAT_NOT_SUPPORTED,
357 "unsupported VkImageUsageFlags(0x%x) for gralloc "
358 "swapchain", imageUsage);
359 }
360
361 /*
362 * FINISHME: Advertise all display-supported formats. Mostly
363 * DRM_FORMAT_ARGB2101010 and DRM_FORMAT_ABGR2101010, but need to check
364 * what we need for 30-bit colors.
365 */
366 if (format == VK_FORMAT_B8G8R8A8_UNORM ||
367 format == VK_FORMAT_B5G6R5_UNORM_PACK16) {
368 *grallocProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
369 *grallocConsumerUsage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER;
370 }
371
372 if (!*grallocProducerUsage && !*grallocConsumerUsage)
373 return VK_ERROR_FORMAT_NOT_SUPPORTED;
374
375 return VK_SUCCESS;
376 #else
377 *grallocConsumerUsage = 0;
378 *grallocProducerUsage = 0;
379 return VK_ERROR_FORMAT_NOT_SUPPORTED;
380 #endif
381 }
382
383 VkResult
384 radv_AcquireImageANDROID(
385 VkDevice device,
386 VkImage image_h,
387 int nativeFenceFd,
388 VkSemaphore semaphore,
389 VkFence fence)
390 {
391 VkResult semaphore_result = VK_SUCCESS, fence_result = VK_SUCCESS;
392
393 if (semaphore != VK_NULL_HANDLE) {
394 int semaphore_fd = nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;
395 semaphore_result = radv_ImportSemaphoreFdKHR(device,
396 &(VkImportSemaphoreFdInfoKHR) {
397 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
398 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
399 .fd = semaphore_fd,
400 .semaphore = semaphore,
401 });
402 }
403
404 if (fence != VK_NULL_HANDLE) {
405 int fence_fd = nativeFenceFd >= 0 ? os_dupfd_cloexec(nativeFenceFd) : nativeFenceFd;
406 fence_result = radv_ImportFenceFdKHR(device,
407 &(VkImportFenceFdInfoKHR) {
408 .sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
409 .flags = VK_FENCE_IMPORT_TEMPORARY_BIT,
410 .fd = fence_fd,
411 .fence = fence,
412 });
413 }
414
415 close(nativeFenceFd);
416
417 if (semaphore_result != VK_SUCCESS)
418 return semaphore_result;
419 return fence_result;
420 }
421
422 VkResult
423 radv_QueueSignalReleaseImageANDROID(
424 VkQueue _queue,
425 uint32_t waitSemaphoreCount,
426 const VkSemaphore* pWaitSemaphores,
427 VkImage image,
428 int* pNativeFenceFd)
429 {
430 RADV_FROM_HANDLE(radv_queue, queue, _queue);
431 VkResult result = VK_SUCCESS;
432
433 if (waitSemaphoreCount == 0) {
434 if (pNativeFenceFd)
435 *pNativeFenceFd = -1;
436 return VK_SUCCESS;
437 }
438
439 int fd = -1;
440
441 for (uint32_t i = 0; i < waitSemaphoreCount; ++i) {
442 int tmp_fd;
443 result = radv_GetSemaphoreFdKHR(radv_device_to_handle(queue->device),
444 &(VkSemaphoreGetFdInfoKHR) {
445 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
446 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
447 .semaphore = pWaitSemaphores[i],
448 }, &tmp_fd);
449 if (result != VK_SUCCESS) {
450 if (fd >= 0)
451 close (fd);
452 return result;
453 }
454
455 if (fd < 0)
456 fd = tmp_fd;
457 else if (tmp_fd >= 0) {
458 sync_accumulate("radv", &fd, tmp_fd);
459 close(tmp_fd);
460 }
461 }
462
463 if (pNativeFenceFd) {
464 *pNativeFenceFd = fd;
465 } else if (fd >= 0) {
466 close(fd);
467 /* We still need to do the exports, to reset the semaphores, but
468 * otherwise we don't wait on them. */
469 }
470 return VK_SUCCESS;
471 }
472 #endif
473
474 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
475
476 enum {
477 /* Usage bit equal to GRALLOC_USAGE_HW_CAMERA_MASK */
478 AHARDWAREBUFFER_USAGE_CAMERA_MASK = 0x00060000U,
479 };
480
481 static inline VkFormat
482 vk_format_from_android(unsigned android_format, unsigned android_usage)
483 {
484 switch (android_format) {
485 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
486 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
487 return VK_FORMAT_R8G8B8A8_UNORM;
488 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
489 return VK_FORMAT_R8G8B8_UNORM;
490 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
491 return VK_FORMAT_R5G6B5_UNORM_PACK16;
492 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
493 return VK_FORMAT_R16G16B16A16_SFLOAT;
494 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
495 return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
496 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
497 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
498 case AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED:
499 if (android_usage & AHARDWAREBUFFER_USAGE_CAMERA_MASK)
500 return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
501 else
502 return VK_FORMAT_R8G8B8_UNORM;
503 case AHARDWAREBUFFER_FORMAT_BLOB:
504 default:
505 return VK_FORMAT_UNDEFINED;
506 }
507 }
508
509 static inline unsigned
510 android_format_from_vk(unsigned vk_format)
511 {
512 switch (vk_format) {
513 case VK_FORMAT_R8G8B8A8_UNORM:
514 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
515 case VK_FORMAT_R8G8B8_UNORM:
516 return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
517 case VK_FORMAT_R5G6B5_UNORM_PACK16:
518 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
519 case VK_FORMAT_R16G16B16A16_SFLOAT:
520 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
521 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
522 return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
523 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
524 return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
525 default:
526 return AHARDWAREBUFFER_FORMAT_BLOB;
527 }
528 }
529
530 uint64_t
531 radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create,
532 const VkImageUsageFlags vk_usage)
533 {
534 uint64_t ahb_usage = 0;
535 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
536 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
537
538 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
539 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
540
541 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
542 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
543
544 if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
545 ahb_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
546
547 if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
548 ahb_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
549
550 /* No usage bits set - set at least one GPU usage. */
551 if (ahb_usage == 0)
552 ahb_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
553 return ahb_usage;
554 }
555
556 static VkResult
557 get_ahb_buffer_format_properties(
558 VkDevice device_h,
559 const struct AHardwareBuffer *buffer,
560 VkAndroidHardwareBufferFormatPropertiesANDROID *pProperties)
561 {
562 RADV_FROM_HANDLE(radv_device, device, device_h);
563
564 /* Get a description of buffer contents . */
565 AHardwareBuffer_Desc desc;
566 AHardwareBuffer_describe(buffer, &desc);
567
568 /* Verify description. */
569 const uint64_t gpu_usage =
570 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
571 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
572 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
573
574 /* "Buffer must be a valid Android hardware buffer object with at least
575 * one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags."
576 */
577 if (!(desc.usage & (gpu_usage)))
578 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
579
580 /* Fill properties fields based on description. */
581 VkAndroidHardwareBufferFormatPropertiesANDROID *p = pProperties;
582
583 p->format = vk_format_from_android(desc.format, desc.usage);
584 p->externalFormat = (uint64_t) (uintptr_t) p->format;
585
586 VkFormatProperties format_properties;
587 radv_GetPhysicalDeviceFormatProperties(
588 radv_physical_device_to_handle(device->physical_device),
589 p->format, &format_properties);
590
591 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER)
592 p->formatFeatures = format_properties.linearTilingFeatures;
593 else
594 p->formatFeatures = format_properties.optimalTilingFeatures;
595
596 /* "Images can be created with an external format even if the Android hardware
597 * buffer has a format which has an equivalent Vulkan format to enable
598 * consistent handling of images from sources that might use either category
599 * of format. However, all images created with an external format are subject
600 * to the valid usage requirements associated with external formats, even if
601 * the Android hardware buffer’s format has a Vulkan equivalent."
602 *
603 * "The formatFeatures member *must* include
604 * VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
605 * VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
606 * VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT"
607 */
608 assert(p->formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
609
610 p->formatFeatures |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
611
612 /* "Implementations may not always be able to determine the color model,
613 * numerical range, or chroma offsets of the image contents, so the values
614 * in VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
615 * Applications should treat these values as sensible defaults to use in
616 * the absence of more reliable information obtained through some other
617 * means."
618 */
619 p->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
620 p->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
621 p->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
622 p->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
623
624 p->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
625 p->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
626
627 p->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
628 p->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
629
630 return VK_SUCCESS;
631 }
632
633 VkResult
634 radv_GetAndroidHardwareBufferPropertiesANDROID(
635 VkDevice device_h,
636 const struct AHardwareBuffer *buffer,
637 VkAndroidHardwareBufferPropertiesANDROID *pProperties)
638 {
639 RADV_FROM_HANDLE(radv_device, dev, device_h);
640 struct radv_physical_device *pdevice = dev->physical_device;
641
642 VkAndroidHardwareBufferFormatPropertiesANDROID *format_prop =
643 vk_find_struct(pProperties->pNext,
644 ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID);
645
646 /* Fill format properties of an Android hardware buffer. */
647 if (format_prop)
648 get_ahb_buffer_format_properties(device_h, buffer, format_prop);
649
650 /* NOTE - We support buffers with only one handle but do not error on
651 * multiple handle case. Reason is that we want to support YUV formats
652 * where we have many logical planes but they all point to the same
653 * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
654 */
655 const native_handle_t *handle =
656 AHardwareBuffer_getNativeHandle(buffer);
657 int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
658 if (dma_buf < 0)
659 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
660
661 /* All memory types. */
662 uint32_t memory_types = (1u << pdevice->memory_properties.memoryTypeCount) - 1;
663
664 pProperties->allocationSize = lseek(dma_buf, 0, SEEK_END);
665 pProperties->memoryTypeBits = memory_types;
666
667 return VK_SUCCESS;
668 }
669
670 VkResult
671 radv_GetMemoryAndroidHardwareBufferANDROID(
672 VkDevice device_h,
673 const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo,
674 struct AHardwareBuffer **pBuffer)
675 {
676 RADV_FROM_HANDLE(radv_device_memory, mem, pInfo->memory);
677
678 /* This should always be set due to the export handle types being set on
679 * allocation. */
680 assert(mem->android_hardware_buffer);
681
682 /* Some quotes from Vulkan spec:
683 *
684 * "If the device memory was created by importing an Android hardware
685 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
686 * Android hardware buffer object."
687 *
688 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
689 * have been included in VkExportMemoryAllocateInfo::handleTypes when
690 * memory was created."
691 */
692 *pBuffer = mem->android_hardware_buffer;
693 /* Increase refcount. */
694 AHardwareBuffer_acquire(mem->android_hardware_buffer);
695 return VK_SUCCESS;
696 }
697
698 #endif
699
700 VkFormat
701 radv_select_android_external_format(const void *next, VkFormat default_format)
702 {
703 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
704 const VkExternalFormatANDROID *android_format =
705 vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID);
706
707 if (android_format && android_format->externalFormat) {
708 return (VkFormat)android_format->externalFormat;
709 }
710 #endif
711
712 return default_format;
713 }
714
715
716 VkResult
717 radv_import_ahb_memory(struct radv_device *device,
718 struct radv_device_memory *mem,
719 unsigned priority,
720 const VkImportAndroidHardwareBufferInfoANDROID *info)
721 {
722 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
723 /* Import from AHardwareBuffer to radv_device_memory. */
724 const native_handle_t *handle =
725 AHardwareBuffer_getNativeHandle(info->buffer);
726
727 /* NOTE - We support buffers with only one handle but do not error on
728 * multiple handle case. Reason is that we want to support YUV formats
729 * where we have many logical planes but they all point to the same
730 * buffer, like is the case with VK_FORMAT_G8_B8R8_2PLANE_420_UNORM.
731 */
732 int dma_buf = (handle && handle->numFds) ? handle->data[0] : -1;
733 if (dma_buf < 0)
734 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
735
736 uint64_t alloc_size = 0;
737 mem->bo = device->ws->buffer_from_fd(device->ws, dma_buf,
738 priority, &alloc_size);
739 if (!mem->bo)
740 return VK_ERROR_OUT_OF_HOST_MEMORY;
741
742 if (mem->image) {
743 struct radeon_bo_metadata metadata;
744 device->ws->buffer_get_metadata(mem->bo, &metadata);
745
746 struct radv_image_create_info create_info = {
747 .no_metadata_planes = true,
748 .bo_metadata = &metadata
749 };
750
751 VkResult result = radv_image_create_layout(device, create_info, mem->image);
752 if (result != VK_SUCCESS) {
753 device->ws->buffer_destroy(mem->bo);
754 mem->bo = NULL;
755 return result;
756 }
757
758 if (alloc_size < mem->image->size) {
759 device->ws->buffer_destroy(mem->bo);
760 mem->bo = NULL;
761 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
762 }
763 } else if (mem->buffer) {
764 if (alloc_size < mem->buffer->size) {
765 device->ws->buffer_destroy(mem->bo);
766 mem->bo = NULL;
767 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
768 }
769 }
770
771 /* "If the vkAllocateMemory command succeeds, the implementation must
772 * acquire a reference to the imported hardware buffer, which it must
773 * release when the device memory object is freed. If the command fails,
774 * the implementation must not retain a reference."
775 */
776 AHardwareBuffer_acquire(info->buffer);
777 mem->android_hardware_buffer = info->buffer;
778
779 return VK_SUCCESS;
780 #else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
781 return VK_ERROR_EXTENSION_NOT_PRESENT;
782 #endif
783 }
784
785 VkResult
786 radv_create_ahb_memory(struct radv_device *device,
787 struct radv_device_memory *mem,
788 unsigned priority,
789 const VkMemoryAllocateInfo *pAllocateInfo)
790 {
791 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
792 const VkMemoryDedicatedAllocateInfo *dedicated_info =
793 vk_find_struct_const(pAllocateInfo->pNext,
794 MEMORY_DEDICATED_ALLOCATE_INFO);
795
796 uint32_t w = 0;
797 uint32_t h = 1;
798 uint32_t layers = 1;
799 uint32_t format = 0;
800 uint64_t usage = 0;
801
802 /* If caller passed dedicated information. */
803 if (dedicated_info && dedicated_info->image) {
804 RADV_FROM_HANDLE(radv_image, image, dedicated_info->image);
805 w = image->info.width;
806 h = image->info.height;
807 layers = image->info.array_size;
808 format = android_format_from_vk(image->vk_format);
809 usage = radv_ahb_usage_from_vk_usage(image->flags, image->usage);
810 } else if (dedicated_info && dedicated_info->buffer) {
811 RADV_FROM_HANDLE(radv_buffer, buffer, dedicated_info->buffer);
812 w = buffer->size;
813 format = AHARDWAREBUFFER_FORMAT_BLOB;
814 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
815 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
816 } else {
817 w = pAllocateInfo->allocationSize;
818 format = AHARDWAREBUFFER_FORMAT_BLOB;
819 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
820 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
821 }
822
823 struct AHardwareBuffer *android_hardware_buffer = NULL;
824 struct AHardwareBuffer_Desc desc = {
825 .width = w,
826 .height = h,
827 .layers = layers,
828 .format = format,
829 .usage = usage,
830 };
831
832 if (AHardwareBuffer_allocate(&desc, &android_hardware_buffer) != 0)
833 return VK_ERROR_OUT_OF_HOST_MEMORY;
834
835 mem->android_hardware_buffer = android_hardware_buffer;
836
837 const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
838 .buffer = mem->android_hardware_buffer,
839 };
840
841 VkResult result = radv_import_ahb_memory(device, mem, priority, &import_info);
842 if (result != VK_SUCCESS)
843 AHardwareBuffer_release(mem->android_hardware_buffer);
844 return result;
845 #else /* RADV_SUPPORT_ANDROID_HARDWARE_BUFFER */
846 return VK_ERROR_EXTENSION_NOT_PRESENT;
847 #endif
848 }
849
850 bool radv_android_gralloc_supports_format(VkFormat format, VkImageUsageFlagBits usage) {
851 #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER
852 /* Ideally we check Gralloc for what it supports and then merge that with the radv
853 format support, but there is no easy gralloc query besides just creating an image.
854 That seems a bit on the expensive side, so just hardcode for now. */
855 /* TODO: Add multi-plane formats after confirming everything works between radeonsi
856 and radv. */
857 switch(format) {
858 case VK_FORMAT_R8G8B8A8_UNORM:
859 case VK_FORMAT_R5G6B5_UNORM_PACK16:
860 return true;
861 case VK_FORMAT_R8_UNORM:
862 case VK_FORMAT_R8G8_UNORM:
863 return !(usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
864 default:
865 return false;
866 }
867 #else
868 (void)format;
869 (void)usage;
870 return false;
871 #endif
872 }