1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * \brief Vulkan external memory utilities
20 *//*--------------------------------------------------------------------*/
21
22 #include "vktExternalMemoryUtil.hpp"
23
24 #include "vkQueryUtil.hpp"
25
26 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
27 # include <unistd.h>
28 # include <fcntl.h>
29 # include <errno.h>
30 # include <sys/types.h>
31 # include <sys/socket.h>
32 #endif
33
34 #if (DE_OS == DE_OS_WIN32)
35 # define WIN32_LEAN_AND_MEAN
36 # include <windows.h>
37 #endif
38
39 #if (DE_OS == DE_OS_ANDROID)
40 # include <sys/system_properties.h>
41 #endif
42
43 #if (DE_OS == DE_OS_ANDROID) && defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
44 # include <android/hardware_buffer.h>
45 # include "deDynamicLibrary.hpp"
46 # define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
47 #endif
48
49 namespace vkt
50 {
51 namespace ExternalMemoryUtil
52 {
53 namespace
54 {
chooseMemoryType(deUint32 bits)55 deUint32 chooseMemoryType (deUint32 bits)
56 {
57 DE_ASSERT(bits != 0);
58
59 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
60 {
61 if ((bits & (1u << memoryTypeIndex)) != 0)
62 return memoryTypeIndex;
63 }
64
65 DE_FATAL("No supported memory types");
66 return -1;
67 }
68
69 } // anonymous
70
NativeHandle(void)71 NativeHandle::NativeHandle (void)
72 : m_fd (-1)
73 , m_win32HandleType (WIN32HANDLETYPE_LAST)
74 , m_win32Handle (DE_NULL)
75 , m_androidHardwareBuffer (DE_NULL)
76 {
77 }
78
NativeHandle(const NativeHandle & other)79 NativeHandle::NativeHandle (const NativeHandle& other)
80 : m_fd (-1)
81 , m_win32HandleType (WIN32HANDLETYPE_LAST)
82 , m_win32Handle (DE_NULL)
83 , m_androidHardwareBuffer (DE_NULL)
84 {
85 if (other.m_fd >= 0)
86 {
87 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
88 DE_ASSERT(!other.m_win32Handle.internal);
89 DE_ASSERT(!other.m_androidHardwareBuffer.internal);
90 m_fd = dup(other.m_fd);
91 TCU_CHECK(m_fd >= 0);
92 #else
93 DE_FATAL("Platform doesn't support file descriptors");
94 #endif
95 }
96 else if (other.m_win32Handle.internal)
97 {
98 #if (DE_OS == DE_OS_WIN32)
99 m_win32HandleType = other.m_win32HandleType;
100
101 switch (other.m_win32HandleType)
102 {
103 case WIN32HANDLETYPE_NT:
104 {
105 DE_ASSERT(other.m_fd == -1);
106 DE_ASSERT(!other.m_androidHardwareBuffer.internal);
107
108 const HANDLE process = ::GetCurrentProcess();
109 ::DuplicateHandle(process, other.m_win32Handle.internal, process, &m_win32Handle.internal, 0, TRUE, DUPLICATE_SAME_ACCESS);
110
111 break;
112 }
113
114 case WIN32HANDLETYPE_KMT:
115 {
116 m_win32Handle = other.m_win32Handle;
117 break;
118 }
119
120 default:
121 DE_FATAL("Unknown win32 handle type");
122 }
123 #else
124 DE_FATAL("Platform doesn't support win32 handles");
125 #endif
126 }
127 else if (other.m_androidHardwareBuffer.internal)
128 {
129 DE_ASSERT(other.m_fd == -1);
130 DE_ASSERT(!other.m_win32Handle.internal);
131 m_androidHardwareBuffer = other.m_androidHardwareBuffer;
132 AndroidHardwareBufferExternalApi::getInstance()->acquire(m_androidHardwareBuffer);
133 }
134 else
135 DE_FATAL("Native handle can't be duplicated");
136 }
137
NativeHandle(int fd)138 NativeHandle::NativeHandle (int fd)
139 : m_fd (fd)
140 , m_win32HandleType (WIN32HANDLETYPE_LAST)
141 , m_win32Handle (DE_NULL)
142 , m_androidHardwareBuffer (DE_NULL)
143 {
144 }
145
NativeHandle(Win32HandleType handleType,vk::pt::Win32Handle handle)146 NativeHandle::NativeHandle (Win32HandleType handleType, vk::pt::Win32Handle handle)
147 : m_fd (-1)
148 , m_win32HandleType (handleType)
149 , m_win32Handle (handle)
150 , m_androidHardwareBuffer (DE_NULL)
151 {
152 }
153
NativeHandle(vk::pt::AndroidHardwareBufferPtr buffer)154 NativeHandle::NativeHandle (vk::pt::AndroidHardwareBufferPtr buffer)
155 : m_fd (-1)
156 , m_win32HandleType (WIN32HANDLETYPE_LAST)
157 , m_win32Handle (DE_NULL)
158 , m_androidHardwareBuffer (buffer)
159 {
160 }
161
~NativeHandle(void)162 NativeHandle::~NativeHandle (void)
163 {
164 reset();
165 }
166
reset(void)167 void NativeHandle::reset (void)
168 {
169 if (m_fd >= 0)
170 {
171 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
172 DE_ASSERT(!m_win32Handle.internal);
173 DE_ASSERT(!m_androidHardwareBuffer.internal);
174 ::close(m_fd);
175 #else
176 DE_FATAL("Platform doesn't support file descriptors");
177 #endif
178 }
179
180 if (m_win32Handle.internal)
181 {
182 #if (DE_OS == DE_OS_WIN32)
183 switch (m_win32HandleType)
184 {
185 case WIN32HANDLETYPE_NT:
186 DE_ASSERT(m_fd == -1);
187 DE_ASSERT(!m_androidHardwareBuffer.internal);
188 ::CloseHandle((HANDLE)m_win32Handle.internal);
189 break;
190
191 case WIN32HANDLETYPE_KMT:
192 break;
193
194 default:
195 DE_FATAL("Unknown win32 handle type");
196 }
197 #else
198 DE_FATAL("Platform doesn't support win32 handles");
199 #endif
200 }
201 if (m_androidHardwareBuffer.internal)
202 {
203 DE_ASSERT(m_fd == -1);
204 DE_ASSERT(!m_win32Handle.internal);
205 AndroidHardwareBufferExternalApi::getInstance()->release(m_androidHardwareBuffer);
206 }
207 m_fd = -1;
208 m_win32Handle = vk::pt::Win32Handle(DE_NULL);
209 m_win32HandleType = WIN32HANDLETYPE_LAST;
210 m_androidHardwareBuffer = vk::pt::AndroidHardwareBufferPtr(DE_NULL);
211 }
212
operator =(int fd)213 NativeHandle& NativeHandle::operator= (int fd)
214 {
215 reset();
216
217 m_fd = fd;
218
219 return *this;
220 }
221
operator =(vk::pt::AndroidHardwareBufferPtr buffer)222 NativeHandle& NativeHandle::operator= (vk::pt::AndroidHardwareBufferPtr buffer)
223 {
224 reset();
225
226 m_androidHardwareBuffer = buffer;
227
228 return *this;
229 }
230
setWin32Handle(Win32HandleType type,vk::pt::Win32Handle handle)231 void NativeHandle::setWin32Handle (Win32HandleType type, vk::pt::Win32Handle handle)
232 {
233 reset();
234
235 m_win32HandleType = type;
236 m_win32Handle = handle;
237 }
238
disown(void)239 void NativeHandle::disown (void)
240 {
241 m_fd = -1;
242 m_win32Handle = vk::pt::Win32Handle(DE_NULL);
243 m_androidHardwareBuffer = vk::pt::AndroidHardwareBufferPtr(DE_NULL);
244 }
245
getWin32Handle(void) const246 vk::pt::Win32Handle NativeHandle::getWin32Handle (void) const
247 {
248 DE_ASSERT(m_fd == -1);
249 DE_ASSERT(!m_androidHardwareBuffer.internal);
250 return m_win32Handle;
251 }
252
getFd(void) const253 int NativeHandle::getFd (void) const
254 {
255 DE_ASSERT(!m_win32Handle.internal);
256 DE_ASSERT(!m_androidHardwareBuffer.internal);
257 return m_fd;
258 }
259
260
getAndroidHardwareBuffer(void) const261 vk::pt::AndroidHardwareBufferPtr NativeHandle::getAndroidHardwareBuffer (void) const
262 {
263 DE_ASSERT(m_fd == -1);
264 DE_ASSERT(!m_win32Handle.internal);
265 return m_androidHardwareBuffer;
266 }
267
externalSemaphoreTypeToName(vk::VkExternalSemaphoreHandleTypeFlagBits type)268 const char* externalSemaphoreTypeToName (vk::VkExternalSemaphoreHandleTypeFlagBits type)
269 {
270 switch (type)
271 {
272 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
273 return "opaque_fd";
274
275 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
276 return "opaque_win32";
277
278 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
279 return "opaque_win32_kmt";
280
281 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT:
282 return "d3d12_fenc";
283
284 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
285 return "sync_fd";
286
287 default:
288 DE_FATAL("Unknown external semaphore type");
289 return DE_NULL;
290 }
291 }
292
externalFenceTypeToName(vk::VkExternalFenceHandleTypeFlagBits type)293 const char* externalFenceTypeToName (vk::VkExternalFenceHandleTypeFlagBits type)
294 {
295 switch (type)
296 {
297 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
298 return "opaque_fd";
299
300 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
301 return "opaque_win32";
302
303 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
304 return "opaque_win32_kmt";
305
306 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
307 return "sync_fd";
308
309 default:
310 DE_FATAL("Unknown external fence type");
311 return DE_NULL;
312 }
313 }
314
externalMemoryTypeToName(vk::VkExternalMemoryHandleTypeFlagBits type)315 const char* externalMemoryTypeToName (vk::VkExternalMemoryHandleTypeFlagBits type)
316 {
317 switch (type)
318 {
319 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
320 return "opaque_fd";
321
322 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
323 return "opaque_win32";
324
325 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
326 return "opaque_win32_kmt";
327
328 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT:
329 return "d3d11_texture";
330
331 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT:
332 return "d3d11_texture_kmt";
333
334 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT:
335 return "d3d12_heap";
336
337 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT:
338 return "d3d12_resource";
339
340 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
341 return "android_hardware_buffer";
342
343 default:
344 DE_FATAL("Unknown external memory type");
345 return DE_NULL;
346 }
347 }
348
isSupportedPermanence(vk::VkExternalSemaphoreHandleTypeFlagBits type,Permanence permanence)349 bool isSupportedPermanence (vk::VkExternalSemaphoreHandleTypeFlagBits type,
350 Permanence permanence)
351 {
352 switch (type)
353 {
354 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
355 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
356 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
357
358 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
359 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
360
361 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
362 return permanence == PERMANENCE_TEMPORARY;
363
364 default:
365 DE_FATAL("Unknown external semaphore type");
366 return false;
367 }
368 }
369
getHandelTypeTransferences(vk::VkExternalSemaphoreHandleTypeFlagBits type)370 Transference getHandelTypeTransferences (vk::VkExternalSemaphoreHandleTypeFlagBits type)
371 {
372 switch (type)
373 {
374 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
375 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
376 return TRANSFERENCE_REFERENCE;
377
378 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
379 return TRANSFERENCE_REFERENCE;
380
381 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
382 return TRANSFERENCE_COPY;
383
384 default:
385 DE_FATAL("Unknown external semaphore type");
386 return TRANSFERENCE_REFERENCE;
387 }
388 }
389
isSupportedPermanence(vk::VkExternalFenceHandleTypeFlagBits type,Permanence permanence)390 bool isSupportedPermanence (vk::VkExternalFenceHandleTypeFlagBits type,
391 Permanence permanence)
392 {
393 switch (type)
394 {
395 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
396 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
397 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
398
399 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
400 return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
401
402 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
403 return permanence == PERMANENCE_TEMPORARY;
404
405 default:
406 DE_FATAL("Unknown external fence type");
407 return false;
408 }
409 }
410
getHandelTypeTransferences(vk::VkExternalFenceHandleTypeFlagBits type)411 Transference getHandelTypeTransferences (vk::VkExternalFenceHandleTypeFlagBits type)
412 {
413 switch (type)
414 {
415 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
416 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
417 return TRANSFERENCE_REFERENCE;
418
419 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
420 return TRANSFERENCE_REFERENCE;
421
422 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
423 return TRANSFERENCE_COPY;
424
425 default:
426 DE_FATAL("Unknown external fence type");
427 return TRANSFERENCE_REFERENCE;
428 }
429 }
430
getMemoryFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkExternalMemoryHandleTypeFlagBits externalType)431 int getMemoryFd (const vk::DeviceInterface& vkd,
432 vk::VkDevice device,
433 vk::VkDeviceMemory memory,
434 vk::VkExternalMemoryHandleTypeFlagBits externalType)
435 {
436 const vk::VkMemoryGetFdInfoKHR info =
437 {
438 vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
439 DE_NULL,
440
441 memory,
442 externalType
443 };
444 int fd = -1;
445
446 VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
447 TCU_CHECK(fd >= 0);
448
449 return fd;
450 }
451
getMemoryNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkExternalMemoryHandleTypeFlagBits externalType,NativeHandle & nativeHandle)452 void getMemoryNative (const vk::DeviceInterface& vkd,
453 vk::VkDevice device,
454 vk::VkDeviceMemory memory,
455 vk::VkExternalMemoryHandleTypeFlagBits externalType,
456 NativeHandle& nativeHandle)
457 {
458 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
459 {
460 const vk::VkMemoryGetFdInfoKHR info =
461 {
462 vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
463 DE_NULL,
464
465 memory,
466 externalType
467 };
468 int fd = -1;
469
470 VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
471 TCU_CHECK(fd >= 0);
472 nativeHandle = fd;
473 }
474 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
475 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
476 {
477 const vk::VkMemoryGetWin32HandleInfoKHR info =
478 {
479 vk::VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
480 DE_NULL,
481
482 memory,
483 externalType
484 };
485 vk::pt::Win32Handle handle (DE_NULL);
486
487 VK_CHECK(vkd.getMemoryWin32HandleKHR(device, &info, &handle));
488
489 switch (externalType)
490 {
491 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
492 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
493 break;
494
495 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
496 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
497 break;
498
499 default:
500 DE_FATAL("Unknown external memory handle type");
501 }
502 }
503 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
504 {
505 if (!AndroidHardwareBufferExternalApi::getInstance())
506 {
507 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
508 }
509 const vk::VkMemoryGetAndroidHardwareBufferInfoANDROID info =
510 {
511 vk::VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
512 DE_NULL,
513
514 memory,
515 };
516 vk::pt::AndroidHardwareBufferPtr ahb (DE_NULL);
517
518 VK_CHECK(vkd.getMemoryAndroidHardwareBufferANDROID(device, &info, &ahb));
519 TCU_CHECK(ahb.internal);
520 nativeHandle = ahb;
521 }
522 else
523 DE_FATAL("Unknown external memory handle type");
524 }
525
createExportableFence(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType)526 vk::Move<vk::VkFence> createExportableFence (const vk::DeviceInterface& vkd,
527 vk::VkDevice device,
528 vk::VkExternalFenceHandleTypeFlagBits externalType)
529 {
530 const vk::VkExportFenceCreateInfo exportCreateInfo =
531 {
532 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
533 DE_NULL,
534 (vk::VkExternalFenceHandleTypeFlags)externalType
535 };
536 const vk::VkFenceCreateInfo createInfo =
537 {
538 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
539 &exportCreateInfo,
540 0u
541 };
542
543 return vk::createFence(vkd, device, &createInfo);
544 }
545
getFenceFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType)546 int getFenceFd (const vk::DeviceInterface& vkd,
547 vk::VkDevice device,
548 vk::VkFence fence,
549 vk::VkExternalFenceHandleTypeFlagBits externalType)
550 {
551 const vk::VkFenceGetFdInfoKHR info =
552 {
553 vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
554 DE_NULL,
555
556 fence,
557 externalType
558 };
559 int fd = -1;
560
561 VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
562 TCU_CHECK(fd >= 0);
563
564 return fd;
565 }
566
getFenceNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & nativeHandle)567 void getFenceNative (const vk::DeviceInterface& vkd,
568 vk::VkDevice device,
569 vk::VkFence fence,
570 vk::VkExternalFenceHandleTypeFlagBits externalType,
571 NativeHandle& nativeHandle)
572 {
573 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
574 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
575 {
576 const vk::VkFenceGetFdInfoKHR info =
577 {
578 vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
579 DE_NULL,
580
581 fence,
582 externalType
583 };
584 int fd = -1;
585
586 VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
587 TCU_CHECK(fd >= 0);
588 nativeHandle = fd;
589 }
590 else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
591 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
592 {
593 const vk::VkFenceGetWin32HandleInfoKHR info =
594 {
595 vk::VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR,
596 DE_NULL,
597
598 fence,
599 externalType
600 };
601 vk::pt::Win32Handle handle (DE_NULL);
602
603 VK_CHECK(vkd.getFenceWin32HandleKHR(device, &info, &handle));
604
605 switch (externalType)
606 {
607 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
608 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
609 break;
610
611 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
612 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
613 break;
614
615 default:
616 DE_FATAL("Unknow external memory handle type");
617 }
618 }
619 else
620 DE_FATAL("Unknow external fence handle type");
621 }
622
importFence(const vk::DeviceInterface & vkd,const vk::VkDevice device,const vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkFenceImportFlags flags)623 void importFence (const vk::DeviceInterface& vkd,
624 const vk::VkDevice device,
625 const vk::VkFence fence,
626 vk::VkExternalFenceHandleTypeFlagBits externalType,
627 NativeHandle& handle,
628 vk::VkFenceImportFlags flags)
629 {
630 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
631 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
632 {
633 const vk::VkImportFenceFdInfoKHR importInfo =
634 {
635 vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
636 DE_NULL,
637 fence,
638 flags,
639 externalType,
640 handle.getFd()
641 };
642
643 VK_CHECK(vkd.importFenceFdKHR(device, &importInfo));
644 handle.disown();
645 }
646 else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
647 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
648 {
649 const vk::VkImportFenceWin32HandleInfoKHR importInfo =
650 {
651 vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR,
652 DE_NULL,
653 fence,
654 flags,
655 externalType,
656 handle.getWin32Handle(),
657 DE_NULL
658 };
659
660 VK_CHECK(vkd.importFenceWin32HandleKHR(device, &importInfo));
661 // \note Importing a fence payload from Windows handles does not transfer ownership of the handle to the Vulkan implementation,
662 // so we do not disown the handle until after all use has complete.
663 }
664 else
665 DE_FATAL("Unknown fence external handle type");
666 }
667
createAndImportFence(const vk::DeviceInterface & vkd,const vk::VkDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkFenceImportFlags flags)668 vk::Move<vk::VkFence> createAndImportFence (const vk::DeviceInterface& vkd,
669 const vk::VkDevice device,
670 vk::VkExternalFenceHandleTypeFlagBits externalType,
671 NativeHandle& handle,
672 vk::VkFenceImportFlags flags)
673 {
674 vk::Move<vk::VkFence> fence (createFence(vkd, device));
675
676 importFence(vkd, device, *fence, externalType, handle, flags);
677
678 return fence;
679 }
680
createExportableSemaphore(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)681 vk::Move<vk::VkSemaphore> createExportableSemaphore (const vk::DeviceInterface& vkd,
682 vk::VkDevice device,
683 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
684 {
685 const vk::VkExportSemaphoreCreateInfo exportCreateInfo =
686 {
687 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
688 DE_NULL,
689 (vk::VkExternalSemaphoreHandleTypeFlags)externalType
690 };
691 const vk::VkSemaphoreCreateInfo createInfo =
692 {
693 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
694 &exportCreateInfo,
695 0u
696 };
697
698 return vk::createSemaphore(vkd, device, &createInfo);
699 }
700
getSemaphoreFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)701 int getSemaphoreFd (const vk::DeviceInterface& vkd,
702 vk::VkDevice device,
703 vk::VkSemaphore semaphore,
704 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
705 {
706 const vk::VkSemaphoreGetFdInfoKHR info =
707 {
708 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
709 DE_NULL,
710
711 semaphore,
712 externalType
713 };
714 int fd = -1;
715
716 VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
717 TCU_CHECK(fd >= 0);
718
719 return fd;
720 }
721
getSemaphoreNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & nativeHandle)722 void getSemaphoreNative (const vk::DeviceInterface& vkd,
723 vk::VkDevice device,
724 vk::VkSemaphore semaphore,
725 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
726 NativeHandle& nativeHandle)
727 {
728 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
729 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
730 {
731 const vk::VkSemaphoreGetFdInfoKHR info =
732 {
733 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
734 DE_NULL,
735
736 semaphore,
737 externalType
738 };
739 int fd = -1;
740
741 VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
742 TCU_CHECK(fd >= 0);
743 nativeHandle = fd;
744 }
745 else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
746 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
747 {
748 const vk::VkSemaphoreGetWin32HandleInfoKHR info =
749 {
750 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
751 DE_NULL,
752
753 semaphore,
754 externalType
755 };
756 vk::pt::Win32Handle handle (DE_NULL);
757
758 VK_CHECK(vkd.getSemaphoreWin32HandleKHR(device, &info, &handle));
759
760 switch (externalType)
761 {
762 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
763 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
764 break;
765
766 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
767 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
768 break;
769
770 default:
771 DE_FATAL("Unknow external memory handle type");
772 }
773 }
774 else
775 DE_FATAL("Unknow external semaphore handle type");
776 }
777
importSemaphore(const vk::DeviceInterface & vkd,const vk::VkDevice device,const vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkSemaphoreImportFlags flags)778 void importSemaphore (const vk::DeviceInterface& vkd,
779 const vk::VkDevice device,
780 const vk::VkSemaphore semaphore,
781 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
782 NativeHandle& handle,
783 vk::VkSemaphoreImportFlags flags)
784 {
785 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
786 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
787 {
788 const vk::VkImportSemaphoreFdInfoKHR importInfo =
789 {
790 vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
791 DE_NULL,
792 semaphore,
793 flags,
794 externalType,
795 handle.getFd()
796 };
797
798 VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo));
799 handle.disown();
800 }
801 else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
802 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
803 {
804 const vk::VkImportSemaphoreWin32HandleInfoKHR importInfo =
805 {
806 vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
807 DE_NULL,
808 semaphore,
809 flags,
810 externalType,
811 handle.getWin32Handle(),
812 DE_NULL
813 };
814
815 VK_CHECK(vkd.importSemaphoreWin32HandleKHR(device, &importInfo));
816 // \note Importing a semaphore payload from Windows handles does not transfer ownership of the handle to the Vulkan implementation,
817 // so we do not disown the handle until after all use has complete.
818 }
819 else
820 DE_FATAL("Unknown semaphore external handle type");
821 }
822
createAndImportSemaphore(const vk::DeviceInterface & vkd,const vk::VkDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkSemaphoreImportFlags flags)823 vk::Move<vk::VkSemaphore> createAndImportSemaphore (const vk::DeviceInterface& vkd,
824 const vk::VkDevice device,
825 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
826 NativeHandle& handle,
827 vk::VkSemaphoreImportFlags flags)
828 {
829 vk::Move<vk::VkSemaphore> semaphore (createSemaphore(vkd, device));
830
831 importSemaphore(vkd, device, *semaphore, externalType, handle, flags);
832
833 return semaphore;
834 }
835
allocateExportableMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkBuffer buffer,deUint32 & exportedMemoryTypeIndex)836 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface& vkd,
837 vk::VkDevice device,
838 const vk::VkMemoryRequirements& requirements,
839 vk::VkExternalMemoryHandleTypeFlagBits externalType,
840 vk::VkBuffer buffer,
841 deUint32& exportedMemoryTypeIndex)
842 {
843 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
844 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
845 {
846 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
847 DE_NULL,
848
849 (vk::VkImage)0,
850 buffer
851 };
852 const vk::VkExportMemoryAllocateInfo exportInfo =
853 {
854 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
855 !!buffer ? &dedicatedInfo : DE_NULL,
856 (vk::VkExternalMemoryHandleTypeFlags)externalType
857 };
858 const vk::VkMemoryAllocateInfo info =
859 {
860 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
861 &exportInfo,
862 requirements.size,
863 exportedMemoryTypeIndex
864 };
865 return vk::allocateMemory(vkd, device, &info);
866 }
867
allocateExportableMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkImage image,deUint32 & exportedMemoryTypeIndex)868 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface& vkd,
869 vk::VkDevice device,
870 const vk::VkMemoryRequirements& requirements,
871 vk::VkExternalMemoryHandleTypeFlagBits externalType,
872 vk::VkImage image,
873 deUint32& exportedMemoryTypeIndex)
874 {
875 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
876 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
877 {
878 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
879 DE_NULL,
880
881 image,
882 (vk::VkBuffer)0
883 };
884 const vk::VkExportMemoryAllocateInfo exportInfo =
885 {
886 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
887 !!image ? &dedicatedInfo : DE_NULL,
888 (vk::VkExternalMemoryHandleTypeFlags)externalType
889 };
890 const vk::VkMemoryAllocateInfo info =
891 {
892 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
893 &exportInfo,
894 requirements.size,
895 exportedMemoryTypeIndex
896 };
897 return vk::allocateMemory(vkd, device, &info);
898 }
899
allocateExportableMemory(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,bool hostVisible,vk::VkBuffer buffer,deUint32 & exportedMemoryTypeIndex)900 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::InstanceInterface& vki,
901 vk::VkPhysicalDevice physicalDevice,
902 const vk::DeviceInterface& vkd,
903 vk::VkDevice device,
904 const vk::VkMemoryRequirements& requirements,
905 vk::VkExternalMemoryHandleTypeFlagBits externalType,
906 bool hostVisible,
907 vk::VkBuffer buffer,
908 deUint32& exportedMemoryTypeIndex)
909 {
910 const vk::VkPhysicalDeviceMemoryProperties properties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
911
912 for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= requirements.memoryTypeBits; memoryTypeIndex++)
913 {
914 if (((requirements.memoryTypeBits & (1u << memoryTypeIndex)) != 0)
915 && (((properties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == hostVisible))
916 {
917 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
918 {
919 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
920 DE_NULL,
921
922 (vk::VkImage)0,
923 buffer
924 };
925 const vk::VkExportMemoryAllocateInfo exportInfo =
926 {
927 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
928 !!buffer ? &dedicatedInfo : DE_NULL,
929 (vk::VkExternalMemoryHandleTypeFlags)externalType
930 };
931 const vk::VkMemoryAllocateInfo info =
932 {
933 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
934 &exportInfo,
935 requirements.size,
936 memoryTypeIndex
937 };
938
939 exportedMemoryTypeIndex = memoryTypeIndex;
940 return vk::allocateMemory(vkd, device, &info);
941 }
942 }
943
944 TCU_THROW(NotSupportedError, "No supported memory type found");
945 }
946
importMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer,vk::VkImage image,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,deUint32 memoryTypeIndex,NativeHandle & handle)947 static vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd,
948 vk::VkDevice device,
949 vk::VkBuffer buffer,
950 vk::VkImage image,
951 const vk::VkMemoryRequirements& requirements,
952 vk::VkExternalMemoryHandleTypeFlagBits externalType,
953 deUint32 memoryTypeIndex,
954 NativeHandle& handle)
955 {
956 const bool isDedicated = !!buffer || !!image;
957
958 DE_ASSERT(!buffer || !image);
959
960 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
961 {
962 const vk::VkImportMemoryFdInfoKHR importInfo =
963 {
964 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
965 DE_NULL,
966 externalType,
967 handle.getFd()
968 };
969 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
970 {
971 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
972 &importInfo,
973 image,
974 buffer,
975 };
976 const vk::VkMemoryAllocateInfo info =
977 {
978 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
979 (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
980 requirements.size,
981 (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex
982 };
983 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
984
985 handle.disown();
986
987 return memory;
988 }
989 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
990 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
991 {
992 const vk::VkImportMemoryWin32HandleInfoKHR importInfo =
993 {
994 vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
995 DE_NULL,
996 externalType,
997 handle.getWin32Handle(),
998 DE_NULL
999 };
1000 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
1001 {
1002 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1003 &importInfo,
1004 image,
1005 buffer,
1006 };
1007 const vk::VkMemoryAllocateInfo info =
1008 {
1009 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1010 (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
1011 requirements.size,
1012 (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex
1013 };
1014 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
1015
1016 // The handle's owned reference must also be released. Do not discard the handle below.
1017 if (externalType != vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)
1018 handle.disown();
1019
1020 return memory;
1021 }
1022 else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
1023 {
1024 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
1025 if (!ahbApi)
1026 {
1027 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
1028 }
1029
1030 deUint32 ahbFormat = 0;
1031 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL);
1032 DE_ASSERT(ahbApi->ahbFormatIsBlob(ahbFormat) || image != 0);
1033
1034 vk::VkImportAndroidHardwareBufferInfoANDROID importInfo =
1035 {
1036 vk::VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
1037 DE_NULL,
1038 handle.getAndroidHardwareBuffer()
1039 };
1040 const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo =
1041 {
1042 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
1043 &importInfo,
1044 image,
1045 buffer,
1046 };
1047 const vk::VkMemoryAllocateInfo info =
1048 {
1049 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1050 (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
1051 requirements.size,
1052 (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex
1053 };
1054 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
1055
1056 return memory;
1057 }
1058 else
1059 {
1060 DE_FATAL("Unknown external memory type");
1061 return vk::Move<vk::VkDeviceMemory>();
1062 }
1063 }
1064
importMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,deUint32 memoryTypeIndex,NativeHandle & handle)1065 vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface& vkd,
1066 vk::VkDevice device,
1067 const vk::VkMemoryRequirements& requirements,
1068 vk::VkExternalMemoryHandleTypeFlagBits externalType,
1069 deUint32 memoryTypeIndex,
1070 NativeHandle& handle)
1071 {
1072 return importMemory(vkd, device, (vk::VkBuffer)0, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle);
1073 }
1074
importDedicatedMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,deUint32 memoryTypeIndex,NativeHandle & handle)1075 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface& vkd,
1076 vk::VkDevice device,
1077 vk::VkBuffer buffer,
1078 const vk::VkMemoryRequirements& requirements,
1079 vk::VkExternalMemoryHandleTypeFlagBits externalType,
1080 deUint32 memoryTypeIndex,
1081 NativeHandle& handle)
1082 {
1083 return importMemory(vkd, device, buffer, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle);
1084 }
1085
importDedicatedMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,deUint32 memoryTypeIndex,NativeHandle & handle)1086 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface& vkd,
1087 vk::VkDevice device,
1088 vk::VkImage image,
1089 const vk::VkMemoryRequirements& requirements,
1090 vk::VkExternalMemoryHandleTypeFlagBits externalType,
1091 deUint32 memoryTypeIndex,
1092 NativeHandle& handle)
1093 {
1094 return importMemory(vkd, device, (vk::VkBuffer)0, image, requirements, externalType, memoryTypeIndex, handle);
1095 }
1096
createExternalBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkDeviceSize size,vk::VkBufferCreateFlags createFlags,vk::VkBufferUsageFlags usageFlags)1097 vk::Move<vk::VkBuffer> createExternalBuffer (const vk::DeviceInterface& vkd,
1098 vk::VkDevice device,
1099 deUint32 queueFamilyIndex,
1100 vk::VkExternalMemoryHandleTypeFlagBits externalType,
1101 vk::VkDeviceSize size,
1102 vk::VkBufferCreateFlags createFlags,
1103 vk::VkBufferUsageFlags usageFlags)
1104 {
1105 const vk::VkExternalMemoryBufferCreateInfo externalCreateInfo =
1106 {
1107 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
1108 DE_NULL,
1109 (vk::VkExternalMemoryHandleTypeFlags)externalType
1110 };
1111 const vk::VkBufferCreateInfo createInfo =
1112 {
1113 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1114 &externalCreateInfo,
1115 createFlags,
1116 size,
1117 usageFlags,
1118 vk::VK_SHARING_MODE_EXCLUSIVE,
1119 1u,
1120 &queueFamilyIndex
1121 };
1122
1123 return vk::createBuffer(vkd, device, &createInfo);
1124 }
1125
createExternalImage(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkFormat format,deUint32 width,deUint32 height,vk::VkImageTiling tiling,vk::VkImageCreateFlags createFlags,vk::VkImageUsageFlags usageFlags,deUint32 mipLevels,deUint32 arrayLayers)1126 vk::Move<vk::VkImage> createExternalImage (const vk::DeviceInterface& vkd,
1127 vk::VkDevice device,
1128 deUint32 queueFamilyIndex,
1129 vk::VkExternalMemoryHandleTypeFlagBits externalType,
1130 vk::VkFormat format,
1131 deUint32 width,
1132 deUint32 height,
1133 vk::VkImageTiling tiling,
1134 vk::VkImageCreateFlags createFlags,
1135 vk::VkImageUsageFlags usageFlags,
1136 deUint32 mipLevels,
1137 deUint32 arrayLayers)
1138 {
1139 const vk::VkExternalMemoryImageCreateInfo externalCreateInfo =
1140 {
1141 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
1142 DE_NULL,
1143 (vk::VkExternalMemoryHandleTypeFlags)externalType
1144 };
1145 const vk::VkImageCreateInfo createInfo =
1146 {
1147 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1148 &externalCreateInfo,
1149 createFlags,
1150 vk::VK_IMAGE_TYPE_2D,
1151 format,
1152 { width, height, 1u, },
1153 mipLevels,
1154 arrayLayers,
1155 vk::VK_SAMPLE_COUNT_1_BIT,
1156 tiling,
1157 usageFlags,
1158 vk::VK_SHARING_MODE_EXCLUSIVE,
1159 1,
1160 &queueFamilyIndex,
1161 vk::VK_IMAGE_LAYOUT_UNDEFINED
1162 };
1163
1164 return vk::createImage(vkd, device, &createInfo);
1165 }
1166
1167 #if (DE_OS == DE_OS_ANDROID)
1168 # if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
1169 # define BUILT_WITH_ANDROID_P_HARDWARE_BUFFER 1
1170 # endif
1171
androidGetSdkVersion()1172 static deInt32 androidGetSdkVersion()
1173 {
1174 static deInt32 sdkVersion = -1;
1175 if (sdkVersion < 0)
1176 {
1177 char value[128] = {0};
1178 __system_property_get("ro.build.version.sdk", value);
1179 sdkVersion = static_cast<deInt32>(strtol(value, DE_NULL, 10));
1180 printf("SDK Version is %d\n", sdkVersion);
1181 }
1182 return sdkVersion;
1183 }
1184
checkAnbApiBuild()1185 static deInt32 checkAnbApiBuild()
1186 {
1187 deInt32 sdkVersion = androidGetSdkVersion();
1188 #if !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1189 // When testing AHB on Android-O and newer the CTS must be compiled against API26 or newer.
1190 DE_TEST_ASSERT(!(sdkVersion >= 26)); /* __ANDROID_API_O__ */
1191 #endif // !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1192 #if !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
1193 // When testing AHB on Android-P and newer the CTS must be compiled against API28 or newer.
1194 DE_TEST_ASSERT(!(sdkVersion >= 28)); /*__ANDROID_API_P__ */
1195 #endif // !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
1196 return sdkVersion;
1197 }
1198
supportsAhb()1199 bool AndroidHardwareBufferExternalApi::supportsAhb()
1200 {
1201 return (checkAnbApiBuild() >= __ANDROID_API_O__);
1202 }
1203
supportsCubeMap()1204 bool AndroidHardwareBufferExternalApi::supportsCubeMap()
1205 {
1206 return (checkAnbApiBuild() >= 28);
1207 }
1208
AndroidHardwareBufferExternalApi()1209 AndroidHardwareBufferExternalApi::AndroidHardwareBufferExternalApi()
1210 {
1211 deInt32 sdkVersion = checkAnbApiBuild();
1212 if(sdkVersion >= __ANDROID_API_O__)
1213 {
1214 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1215 if (!loadAhbDynamicApis(sdkVersion))
1216 {
1217 // Couldn't load Android AHB system APIs.
1218 DE_TEST_ASSERT(false);
1219 }
1220 #else
1221 // Invalid Android AHB APIs configuration. Please check the instructions on how to build NDK for Android.
1222 DE_TEST_ASSERT(false);
1223 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1224 }
1225 }
1226
~AndroidHardwareBufferExternalApi()1227 AndroidHardwareBufferExternalApi::~AndroidHardwareBufferExternalApi()
1228 {
1229 }
1230
1231 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1232 typedef int (*pfn_system_property_get)(const char *, char *);
1233 typedef int (*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer);
1234 typedef void (*pfnAHardwareBuffer_describe)(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc);
1235 typedef void (*pfnAHardwareBuffer_acquire)(AHardwareBuffer* buffer);
1236 typedef void (*pfnAHardwareBuffer_release)(AHardwareBuffer* buffer);
1237
1238 struct AhbFunctions
1239 {
1240 pfnAHardwareBuffer_allocate allocate;
1241 pfnAHardwareBuffer_describe describe;
1242 pfnAHardwareBuffer_acquire acquire;
1243 pfnAHardwareBuffer_release release;
1244 };
1245
1246 static AhbFunctions ahbFunctions;
1247
ahbFunctionsLoaded(AhbFunctions * pAhbFunctions)1248 static bool ahbFunctionsLoaded(AhbFunctions* pAhbFunctions)
1249 {
1250 static bool ahbApiLoaded = false;
1251 if (ahbApiLoaded ||
1252 ((pAhbFunctions->allocate != DE_NULL) &&
1253 (pAhbFunctions->describe != DE_NULL) &&
1254 (pAhbFunctions->acquire != DE_NULL) &&
1255 (pAhbFunctions->release != DE_NULL)))
1256 {
1257 ahbApiLoaded = true;
1258 return true;
1259 }
1260 return false;
1261 }
1262
loadAhbDynamicApis(deInt32 sdkVersion)1263 bool AndroidHardwareBufferExternalApi::loadAhbDynamicApis(deInt32 sdkVersion)
1264 {
1265 if(sdkVersion >= __ANDROID_API_O__)
1266 {
1267 if (!ahbFunctionsLoaded(&ahbFunctions))
1268 {
1269 de::DynamicLibrary libnativewindow("libnativewindow.so");
1270 ahbFunctions.allocate = reinterpret_cast<pfnAHardwareBuffer_allocate>(libnativewindow.getFunction("AHardwareBuffer_allocate"));
1271 ahbFunctions.describe = reinterpret_cast<pfnAHardwareBuffer_describe>(libnativewindow.getFunction("AHardwareBuffer_describe"));
1272 ahbFunctions.acquire = reinterpret_cast<pfnAHardwareBuffer_acquire>(libnativewindow.getFunction("AHardwareBuffer_acquire"));
1273 ahbFunctions.release = reinterpret_cast<pfnAHardwareBuffer_release>(libnativewindow.getFunction("AHardwareBuffer_release"));
1274
1275 return ahbFunctionsLoaded(&ahbFunctions);
1276
1277 }
1278 else
1279 {
1280 return true;
1281 }
1282 }
1283
1284 return false;
1285 }
1286
1287 class AndroidHardwareBufferExternalApi26 : public AndroidHardwareBufferExternalApi
1288 {
1289 public:
1290
1291 virtual vk::pt::AndroidHardwareBufferPtr allocate(deUint32 width, deUint32 height, deUint32 layers, deUint32 format, deUint64 usage);
1292 virtual void acquire(vk::pt::AndroidHardwareBufferPtr buffer);
1293 virtual void release(vk::pt::AndroidHardwareBufferPtr buffer);
1294 virtual void describe(const vk::pt::AndroidHardwareBufferPtr buffer,
1295 deUint32* width,
1296 deUint32* height,
1297 deUint32* layers,
1298 deUint32* format,
1299 deUint64* usage,
1300 deUint32* stride);
1301 virtual deUint64 vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlag);
1302 virtual deUint64 vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag);
1303 virtual deUint32 vkFormatToAhbFormat(vk::VkFormat vkFormat);
1304 virtual deUint64 mustSupportAhbUsageFlags();
ahbFormatIsBlob(deUint32 ahbFormat)1305 virtual bool ahbFormatIsBlob(deUint32 ahbFormat) { return (ahbFormat == AHARDWAREBUFFER_FORMAT_BLOB); };
1306
AndroidHardwareBufferExternalApi26()1307 AndroidHardwareBufferExternalApi26() : AndroidHardwareBufferExternalApi() {};
~AndroidHardwareBufferExternalApi26()1308 virtual ~AndroidHardwareBufferExternalApi26() {};
1309
1310 private:
1311 // Stop the compiler generating methods of copy the object
1312 AndroidHardwareBufferExternalApi26(AndroidHardwareBufferExternalApi26 const& copy); // Not Implemented
1313 AndroidHardwareBufferExternalApi26& operator=(AndroidHardwareBufferExternalApi26 const& copy); // Not Implemented
1314 };
1315
allocate(deUint32 width,deUint32 height,deUint32 layers,deUint32 format,deUint64 usage)1316 vk::pt::AndroidHardwareBufferPtr AndroidHardwareBufferExternalApi26::allocate( deUint32 width,
1317 deUint32 height,
1318 deUint32 layers,
1319 deUint32 format,
1320 deUint64 usage)
1321 {
1322 AHardwareBuffer_Desc hbufferdesc = {
1323 width,
1324 height,
1325 layers, // number of images
1326 format,
1327 usage,
1328 0u, // Stride in pixels, ignored for AHardwareBuffer_allocate()
1329 0u, // Initialize to zero, reserved for future use
1330 0u // Initialize to zero, reserved for future use
1331 };
1332
1333 AHardwareBuffer* hbuffer = DE_NULL;
1334 ahbFunctions.allocate(&hbufferdesc, &hbuffer);
1335
1336 return vk::pt::AndroidHardwareBufferPtr(hbuffer);
1337 }
1338
acquire(vk::pt::AndroidHardwareBufferPtr buffer)1339 void AndroidHardwareBufferExternalApi26::acquire(vk::pt::AndroidHardwareBufferPtr buffer)
1340 {
1341 ahbFunctions.acquire(static_cast<AHardwareBuffer*>(buffer.internal));
1342 }
1343
release(vk::pt::AndroidHardwareBufferPtr buffer)1344 void AndroidHardwareBufferExternalApi26::release(vk::pt::AndroidHardwareBufferPtr buffer)
1345 {
1346 ahbFunctions.release(static_cast<AHardwareBuffer*>(buffer.internal));
1347 }
1348
describe(const vk::pt::AndroidHardwareBufferPtr buffer,deUint32 * width,deUint32 * height,deUint32 * layers,deUint32 * format,deUint64 * usage,deUint32 * stride)1349 void AndroidHardwareBufferExternalApi26::describe( const vk::pt::AndroidHardwareBufferPtr buffer,
1350 deUint32* width,
1351 deUint32* height,
1352 deUint32* layers,
1353 deUint32* format,
1354 deUint64* usage,
1355 deUint32* stride)
1356 {
1357 AHardwareBuffer_Desc desc;
1358 ahbFunctions.describe(static_cast<const AHardwareBuffer*>(buffer.internal), &desc);
1359 if (width) *width = desc.width;
1360 if (height) *height = desc.height;
1361 if (layers) *layers = desc.layers;
1362 if (format) *format = desc.format;
1363 if (usage) *usage = desc.usage;
1364 if (stride) *stride = desc.stride;
1365 }
1366
vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlags)1367 deUint64 AndroidHardwareBufferExternalApi26::vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlags)
1368 {
1369 switch(vkFlags)
1370 {
1371 case vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
1372 case vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT:
1373 // No AHB equivalent.
1374 return 0u;
1375 case vk::VK_IMAGE_USAGE_SAMPLED_BIT:
1376 return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1377 case vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
1378 return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1379 case vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
1380 return AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
1381 default:
1382 return 0u;
1383 }
1384 }
1385
vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)1386 deUint64 AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
1387 {
1388 switch(vkFlags)
1389 {
1390 case vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT:
1391 case vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT:
1392 // No AHB equivalent.
1393 return 0u;
1394 case vk::VK_IMAGE_CREATE_PROTECTED_BIT:
1395 return AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
1396 default:
1397 return 0u;
1398 }
1399 }
1400
vkFormatToAhbFormat(vk::VkFormat vkFormat)1401 deUint32 AndroidHardwareBufferExternalApi26::vkFormatToAhbFormat(vk::VkFormat vkFormat)
1402 {
1403 switch(vkFormat)
1404 {
1405 case vk::VK_FORMAT_R8G8B8A8_UNORM:
1406 return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
1407 case vk::VK_FORMAT_R8G8B8_UNORM:
1408 return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
1409 case vk::VK_FORMAT_R5G6B5_UNORM_PACK16:
1410 return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
1411 case vk::VK_FORMAT_R16G16B16A16_SFLOAT:
1412 return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
1413 case vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1414 return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
1415 default:
1416 return 0u;
1417 }
1418 }
1419
mustSupportAhbUsageFlags()1420 deUint64 AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags()
1421 {
1422 return (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT);
1423 }
1424
1425 #if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
1426 class AndroidHardwareBufferExternalApi28 : public AndroidHardwareBufferExternalApi26
1427 {
1428 public:
1429
1430 virtual deUint64 vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag);
1431 virtual deUint64 mustSupportAhbUsageFlags();
1432
AndroidHardwareBufferExternalApi28()1433 AndroidHardwareBufferExternalApi28() : AndroidHardwareBufferExternalApi26() {};
~AndroidHardwareBufferExternalApi28()1434 virtual ~AndroidHardwareBufferExternalApi28() {};
1435
1436 private:
1437 // Stop the compiler generating methods of copy the object
1438 AndroidHardwareBufferExternalApi28(AndroidHardwareBufferExternalApi28 const& copy); // Not Implemented
1439 AndroidHardwareBufferExternalApi28& operator=(AndroidHardwareBufferExternalApi28 const& copy); // Not Implemented
1440 };
1441
vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)1442 deUint64 AndroidHardwareBufferExternalApi28::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
1443 {
1444 switch(vkFlags)
1445 {
1446 case vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT:
1447 return AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
1448 default:
1449 return AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vkFlags);
1450 }
1451 }
1452
mustSupportAhbUsageFlags()1453 deUint64 AndroidHardwareBufferExternalApi28::mustSupportAhbUsageFlags()
1454 {
1455 return AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags() | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
1456 }
1457
1458 #endif // defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
1459 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1460 #endif // (DE_OS == DE_OS_ANDROID)
1461
getInstance()1462 AndroidHardwareBufferExternalApi* AndroidHardwareBufferExternalApi::getInstance()
1463 {
1464 #if (DE_OS == DE_OS_ANDROID)
1465 deInt32 sdkVersion = checkAnbApiBuild();
1466 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1467 # if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
1468 if (sdkVersion >= __ANDROID_API_P__ )
1469 {
1470 static AndroidHardwareBufferExternalApi28 api28Instance;
1471 return &api28Instance;
1472 }
1473 # endif
1474 # if defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
1475 if (sdkVersion >= __ANDROID_API_O__ )
1476 {
1477 static AndroidHardwareBufferExternalApi26 api26Instance;
1478 return &api26Instance;
1479 }
1480 # endif
1481 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1482 DE_UNREF(sdkVersion);
1483 #endif // DE_OS == DE_OS_ANDROID
1484 return DE_NULL;
1485 }
1486
1487 } // ExternalMemoryUtil
1488 } // vkt
1489