xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/util/vktExternalMemoryUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 #ifndef CTS_USES_VULKANSC
27 
28 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #endif
35 
36 #if (DE_OS == DE_OS_WIN32)
37 #define WIN32_LEAN_AND_MEAN
38 #define NOMINMAX
39 #include <windows.h>
40 #endif
41 
42 #if (DE_OS == DE_OS_FUCHSIA)
43 #include <zircon/syscalls.h>
44 #include <zircon/types.h>
45 #endif
46 
47 #include <limits>
48 
49 namespace vkt
50 {
51 namespace ExternalMemoryUtil
52 {
53 namespace
54 {
55 
56 constexpr int kInvalidFd = std::numeric_limits<int>::min();
57 
58 } // namespace
59 
NativeHandle(void)60 NativeHandle::NativeHandle(void)
61     : m_fd(kInvalidFd)
62     , m_zirconHandle(0)
63     , m_win32HandleType(WIN32HANDLETYPE_LAST)
64     , m_win32Handle(DE_NULL)
65     , m_androidHardwareBuffer(DE_NULL)
66     , m_hostPtr(DE_NULL)
67 {
68 }
69 
NativeHandle(const NativeHandle & other)70 NativeHandle::NativeHandle(const NativeHandle &other)
71     : m_fd(kInvalidFd)
72     , m_zirconHandle(0)
73     , m_win32HandleType(WIN32HANDLETYPE_LAST)
74     , m_win32Handle(DE_NULL)
75     , m_androidHardwareBuffer(DE_NULL)
76     , m_hostPtr(DE_NULL)
77 {
78     if (other.m_fd >= 0)
79     {
80 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
81         DE_ASSERT(!other.m_win32Handle.internal);
82         DE_ASSERT(!other.m_androidHardwareBuffer.internal);
83         m_fd = dup(other.m_fd);
84         TCU_CHECK(m_fd >= 0);
85 #else
86         DE_FATAL("Platform doesn't support file descriptors");
87 #endif
88     }
89     else if (other.m_zirconHandle.internal)
90     {
91 #if (DE_OS == DE_OS_FUCHSIA)
92         DE_ASSERT(!other.m_win32Handle.internal);
93         zx_handle_duplicate(other.m_zirconHandle.internal, ZX_RIGHT_SAME_RIGHTS, &m_zirconHandle.internal);
94 #else
95         DE_FATAL("Platform doesn't support zircon handles");
96 #endif
97     }
98     else if (other.m_win32Handle.internal)
99     {
100 #if (DE_OS == DE_OS_WIN32)
101         m_win32HandleType = other.m_win32HandleType;
102 
103         switch (other.m_win32HandleType)
104         {
105         case WIN32HANDLETYPE_NT:
106         {
107             DE_ASSERT(other.m_fd == kInvalidFd);
108             DE_ASSERT(!other.m_androidHardwareBuffer.internal);
109 
110             const HANDLE process = ::GetCurrentProcess();
111             ::DuplicateHandle(process, other.m_win32Handle.internal, process, &m_win32Handle.internal, 0, TRUE,
112                               DUPLICATE_SAME_ACCESS);
113 
114             break;
115         }
116 
117         case WIN32HANDLETYPE_KMT:
118         {
119             m_win32Handle = other.m_win32Handle;
120             break;
121         }
122 
123         default:
124             DE_FATAL("Unknown win32 handle type");
125         }
126 #else
127         DE_FATAL("Platform doesn't support win32 handles");
128 #endif
129     }
130     else if (other.m_androidHardwareBuffer.internal)
131     {
132         DE_ASSERT(other.m_fd == kInvalidFd);
133         DE_ASSERT(!other.m_win32Handle.internal);
134         m_androidHardwareBuffer = other.m_androidHardwareBuffer;
135 
136         if (AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance())
137             ahbApi->acquire(m_androidHardwareBuffer);
138         else
139             DE_FATAL("Platform doesn't support Android Hardware Buffer handles");
140     }
141     else
142         DE_FATAL("Native handle can't be duplicated");
143 }
144 
NativeHandle(int fd)145 NativeHandle::NativeHandle(int fd)
146     : m_fd(fd)
147     , m_zirconHandle(0)
148     , m_win32HandleType(WIN32HANDLETYPE_LAST)
149     , m_win32Handle(DE_NULL)
150     , m_androidHardwareBuffer(DE_NULL)
151     , m_hostPtr(DE_NULL)
152 {
153 }
154 
NativeHandle(Win32HandleType handleType,vk::pt::Win32Handle handle)155 NativeHandle::NativeHandle(Win32HandleType handleType, vk::pt::Win32Handle handle)
156     : m_fd(kInvalidFd)
157     , m_zirconHandle(0)
158     , m_win32HandleType(handleType)
159     , m_win32Handle(handle)
160     , m_androidHardwareBuffer(DE_NULL)
161     , m_hostPtr(DE_NULL)
162 {
163 }
164 
NativeHandle(vk::pt::AndroidHardwareBufferPtr buffer)165 NativeHandle::NativeHandle(vk::pt::AndroidHardwareBufferPtr buffer)
166     : m_fd(kInvalidFd)
167     , m_zirconHandle(0)
168     , m_win32HandleType(WIN32HANDLETYPE_LAST)
169     , m_win32Handle(DE_NULL)
170     , m_androidHardwareBuffer(buffer)
171     , m_hostPtr(DE_NULL)
172 {
173 }
174 
~NativeHandle(void)175 NativeHandle::~NativeHandle(void)
176 {
177     reset();
178 }
179 
reset(void)180 void NativeHandle::reset(void)
181 {
182     if (m_fd >= 0)
183     {
184 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
185         DE_ASSERT(!m_win32Handle.internal);
186         DE_ASSERT(!m_androidHardwareBuffer.internal);
187         ::close(m_fd);
188 #else
189         DE_FATAL("Platform doesn't support file descriptors");
190 #endif
191     }
192 
193     if (m_zirconHandle.internal != 0)
194     {
195 #if (DE_OS == DE_OS_FUCHSIA)
196         zx_handle_close(m_zirconHandle.internal);
197 #else
198         DE_FATAL("Platform doesn't support fuchsia handles");
199 #endif
200     }
201 
202     if (m_win32Handle.internal)
203     {
204 #if (DE_OS == DE_OS_WIN32)
205         switch (m_win32HandleType)
206         {
207         case WIN32HANDLETYPE_NT:
208             DE_ASSERT(m_fd == kInvalidFd);
209             DE_ASSERT(!m_androidHardwareBuffer.internal);
210             ::CloseHandle((HANDLE)m_win32Handle.internal);
211             break;
212 
213         case WIN32HANDLETYPE_KMT:
214             break;
215 
216         default:
217             DE_FATAL("Unknown win32 handle type");
218         }
219 #else
220         DE_FATAL("Platform doesn't support win32 handles");
221 #endif
222     }
223     if (m_androidHardwareBuffer.internal)
224     {
225         DE_ASSERT(m_fd == kInvalidFd);
226         DE_ASSERT(!m_win32Handle.internal);
227 
228         if (AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance())
229             ahbApi->release(m_androidHardwareBuffer);
230         else
231             DE_FATAL("Platform doesn't support Android Hardware Buffer handles");
232     }
233     m_fd                    = kInvalidFd;
234     m_zirconHandle          = vk::pt::zx_handle_t(0);
235     m_win32Handle           = vk::pt::Win32Handle(DE_NULL);
236     m_win32HandleType       = WIN32HANDLETYPE_LAST;
237     m_androidHardwareBuffer = vk::pt::AndroidHardwareBufferPtr(DE_NULL);
238     m_hostPtr               = DE_NULL;
239 }
240 
operator =(int fd)241 NativeHandle &NativeHandle::operator=(int fd)
242 {
243     reset();
244 
245     m_fd = fd;
246 
247     return *this;
248 }
249 
operator =(vk::pt::AndroidHardwareBufferPtr buffer)250 NativeHandle &NativeHandle::operator=(vk::pt::AndroidHardwareBufferPtr buffer)
251 {
252     reset();
253 
254     m_androidHardwareBuffer = buffer;
255 
256     return *this;
257 }
258 
setWin32Handle(Win32HandleType type,vk::pt::Win32Handle handle)259 void NativeHandle::setWin32Handle(Win32HandleType type, vk::pt::Win32Handle handle)
260 {
261     reset();
262 
263     m_win32HandleType = type;
264     m_win32Handle     = handle;
265 }
266 
setZirconHandle(vk::pt::zx_handle_t zirconHandle)267 void NativeHandle::setZirconHandle(vk::pt::zx_handle_t zirconHandle)
268 {
269     reset();
270 
271     m_zirconHandle = zirconHandle;
272 }
273 
setHostPtr(void * hostPtr)274 void NativeHandle::setHostPtr(void *hostPtr)
275 {
276     reset();
277 
278     m_hostPtr = hostPtr;
279 }
280 
disown(void)281 void NativeHandle::disown(void)
282 {
283     m_fd                    = kInvalidFd;
284     m_zirconHandle          = vk::pt::zx_handle_t(0);
285     m_win32Handle           = vk::pt::Win32Handle(DE_NULL);
286     m_androidHardwareBuffer = vk::pt::AndroidHardwareBufferPtr(DE_NULL);
287     m_hostPtr               = DE_NULL;
288 }
289 
getWin32Handle(void) const290 vk::pt::Win32Handle NativeHandle::getWin32Handle(void) const
291 {
292     DE_ASSERT(m_fd == kInvalidFd);
293     DE_ASSERT(!m_androidHardwareBuffer.internal);
294     DE_ASSERT(m_hostPtr == DE_NULL);
295 
296     return m_win32Handle;
297 }
298 
hasValidFd(void) const299 bool NativeHandle::hasValidFd(void) const
300 {
301     return (m_fd != kInvalidFd);
302 }
303 
getFd(void) const304 int NativeHandle::getFd(void) const
305 {
306     DE_ASSERT(!m_win32Handle.internal);
307     DE_ASSERT(!m_androidHardwareBuffer.internal);
308     DE_ASSERT(m_hostPtr == DE_NULL);
309     return m_fd;
310 }
311 
getZirconHandle(void) const312 vk::pt::zx_handle_t NativeHandle::getZirconHandle(void) const
313 {
314     DE_ASSERT(!m_win32Handle.internal);
315     DE_ASSERT(!m_androidHardwareBuffer.internal);
316 
317     return m_zirconHandle;
318 }
319 
getAndroidHardwareBuffer(void) const320 vk::pt::AndroidHardwareBufferPtr NativeHandle::getAndroidHardwareBuffer(void) const
321 {
322     DE_ASSERT(m_fd == kInvalidFd);
323     DE_ASSERT(!m_win32Handle.internal);
324     DE_ASSERT(m_hostPtr == DE_NULL);
325     return m_androidHardwareBuffer;
326 }
327 
getHostPtr(void) const328 void *NativeHandle::getHostPtr(void) const
329 {
330     DE_ASSERT(m_fd == kInvalidFd);
331     DE_ASSERT(!m_win32Handle.internal);
332     return m_hostPtr;
333 }
334 
externalSemaphoreTypeToName(vk::VkExternalSemaphoreHandleTypeFlagBits type)335 const char *externalSemaphoreTypeToName(vk::VkExternalSemaphoreHandleTypeFlagBits type)
336 {
337     switch (type)
338     {
339     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
340         return "opaque_fd";
341 
342     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
343         return "opaque_win32";
344 
345     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
346         return "opaque_win32_kmt";
347 
348     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT:
349         return "d3d12_fenc";
350 
351     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
352         return "sync_fd";
353 
354     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA:
355         return "zircon_event";
356 
357     default:
358         DE_FATAL("Unknown external semaphore type");
359         return DE_NULL;
360     }
361 }
362 
externalFenceTypeToName(vk::VkExternalFenceHandleTypeFlagBits type)363 const char *externalFenceTypeToName(vk::VkExternalFenceHandleTypeFlagBits type)
364 {
365     switch (type)
366     {
367     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
368         return "opaque_fd";
369 
370     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
371         return "opaque_win32";
372 
373     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
374         return "opaque_win32_kmt";
375 
376     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
377         return "sync_fd";
378 
379     default:
380         DE_FATAL("Unknown external fence type");
381         return DE_NULL;
382     }
383 }
384 
externalMemoryTypeToName(vk::VkExternalMemoryHandleTypeFlagBits type)385 const char *externalMemoryTypeToName(vk::VkExternalMemoryHandleTypeFlagBits type)
386 {
387     switch (type)
388     {
389     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
390         return "opaque_fd";
391 
392     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
393         return "opaque_win32";
394 
395     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
396         return "opaque_win32_kmt";
397 
398     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT:
399         return "d3d11_texture";
400 
401     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT:
402         return "d3d11_texture_kmt";
403 
404     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT:
405         return "d3d12_heap";
406 
407     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT:
408         return "d3d12_resource";
409 
410     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
411         return "android_hardware_buffer";
412 
413     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
414         return "dma_buf";
415 
416     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
417         return "host_allocation";
418 
419     case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA:
420         return "zircon_vmo";
421 
422     default:
423         DE_FATAL("Unknown external memory type");
424         return DE_NULL;
425     }
426 }
427 
isSupportedPermanence(vk::VkExternalSemaphoreHandleTypeFlagBits type,Permanence permanence)428 bool isSupportedPermanence(vk::VkExternalSemaphoreHandleTypeFlagBits type, Permanence permanence)
429 {
430     switch (type)
431     {
432     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
433     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
434         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
435 
436     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
437         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
438 
439     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
440         return permanence == PERMANENCE_TEMPORARY;
441 
442     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA:
443         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
444 
445     default:
446         DE_FATAL("Unknown external semaphore type");
447         return false;
448     }
449 }
450 
getHandelTypeTransferences(vk::VkExternalSemaphoreHandleTypeFlagBits type)451 Transference getHandelTypeTransferences(vk::VkExternalSemaphoreHandleTypeFlagBits type)
452 {
453     switch (type)
454     {
455     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
456     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
457         return TRANSFERENCE_REFERENCE;
458 
459     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
460         return TRANSFERENCE_REFERENCE;
461 
462     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
463         return TRANSFERENCE_COPY;
464 
465     case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA:
466         return TRANSFERENCE_REFERENCE;
467 
468     default:
469         DE_FATAL("Unknown external semaphore type");
470         return TRANSFERENCE_REFERENCE;
471     }
472 }
473 
isSupportedPermanence(vk::VkExternalFenceHandleTypeFlagBits type,Permanence permanence)474 bool isSupportedPermanence(vk::VkExternalFenceHandleTypeFlagBits type, Permanence permanence)
475 {
476     switch (type)
477     {
478     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
479     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
480         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
481 
482     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
483         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
484 
485     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
486         return permanence == PERMANENCE_TEMPORARY;
487 
488     default:
489         DE_FATAL("Unknown external fence type");
490         return false;
491     }
492 }
493 
getHandelTypeTransferences(vk::VkExternalFenceHandleTypeFlagBits type)494 Transference getHandelTypeTransferences(vk::VkExternalFenceHandleTypeFlagBits type)
495 {
496     switch (type)
497     {
498     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
499     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
500         return TRANSFERENCE_REFERENCE;
501 
502     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
503         return TRANSFERENCE_REFERENCE;
504 
505     case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
506         return TRANSFERENCE_COPY;
507 
508     default:
509         DE_FATAL("Unknown external fence type");
510         return TRANSFERENCE_REFERENCE;
511     }
512 }
513 
getMemoryFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkExternalMemoryHandleTypeFlagBits externalType)514 int getMemoryFd(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkDeviceMemory memory,
515                 vk::VkExternalMemoryHandleTypeFlagBits externalType)
516 {
517     const vk::VkMemoryGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, DE_NULL,
518 
519                                            memory, externalType};
520     int fd                              = kInvalidFd;
521 
522     VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
523     TCU_CHECK(fd >= 0);
524 
525     return fd;
526 }
527 
getMemoryNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,vk::VkExternalMemoryHandleTypeFlagBits externalType,NativeHandle & nativeHandle)528 void getMemoryNative(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkDeviceMemory memory,
529                      vk::VkExternalMemoryHandleTypeFlagBits externalType, NativeHandle &nativeHandle)
530 {
531     if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
532         externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
533     {
534         const vk::VkMemoryGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, DE_NULL,
535 
536                                                memory, externalType};
537         int fd                              = kInvalidFd;
538 
539         VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
540         TCU_CHECK(fd >= 0);
541         nativeHandle = fd;
542     }
543     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
544     {
545         const vk::VkMemoryGetZirconHandleInfoFUCHSIA info = {
546             vk::VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA, DE_NULL,
547 
548             memory, externalType};
549         vk::pt::zx_handle_t handle(0);
550 
551         VK_CHECK(vkd.getMemoryZirconHandleFUCHSIA(device, &info, &handle));
552         nativeHandle.setZirconHandle(handle);
553     }
554     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
555              externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
556     {
557         const vk::VkMemoryGetWin32HandleInfoKHR info = {vk::VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, DE_NULL,
558 
559                                                         memory, externalType};
560         vk::pt::Win32Handle handle(DE_NULL);
561 
562         VK_CHECK(vkd.getMemoryWin32HandleKHR(device, &info, &handle));
563 
564         switch (externalType)
565         {
566         case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
567             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
568             break;
569 
570         case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
571             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
572             break;
573 
574         default:
575             DE_FATAL("Unknown external memory handle type");
576         }
577     }
578     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
579     {
580         if (!AndroidHardwareBufferExternalApi::getInstance())
581         {
582             TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
583         }
584         const vk::VkMemoryGetAndroidHardwareBufferInfoANDROID info = {
585             vk::VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
586             DE_NULL,
587 
588             memory,
589         };
590         vk::pt::AndroidHardwareBufferPtr ahb(DE_NULL);
591 
592         VK_CHECK(vkd.getMemoryAndroidHardwareBufferANDROID(device, &info, &ahb));
593         TCU_CHECK(ahb.internal);
594         nativeHandle = ahb;
595     }
596     else
597         DE_FATAL("Unknown external memory handle type");
598 }
599 
createExportableFence(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType)600 vk::Move<vk::VkFence> createExportableFence(const vk::DeviceInterface &vkd, vk::VkDevice device,
601                                             vk::VkExternalFenceHandleTypeFlagBits externalType)
602 {
603     const vk::VkExportFenceCreateInfo exportCreateInfo = {vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, DE_NULL,
604                                                           (vk::VkExternalFenceHandleTypeFlags)externalType};
605     const vk::VkFenceCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, &exportCreateInfo, 0u};
606 
607     return vk::createFence(vkd, device, &createInfo);
608 }
609 
getFenceFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType)610 int getFenceFd(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkFence fence,
611                vk::VkExternalFenceHandleTypeFlagBits externalType)
612 {
613     const vk::VkFenceGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, DE_NULL,
614 
615                                           fence, externalType};
616     int fd                             = kInvalidFd;
617 
618     VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
619     TCU_CHECK(fd >= 0);
620 
621     return fd;
622 }
623 
getFenceNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & nativeHandle,bool expectFenceUnsignaled)624 void getFenceNative(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkFence fence,
625                     vk::VkExternalFenceHandleTypeFlagBits externalType, NativeHandle &nativeHandle,
626                     bool expectFenceUnsignaled)
627 {
628     if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT ||
629         externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
630     {
631         const vk::VkFenceGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, DE_NULL,
632 
633                                               fence, externalType};
634         int fd                             = kInvalidFd;
635 
636         VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
637 
638         if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
639         {
640             TCU_CHECK(!expectFenceUnsignaled || (fd >= 0) || (fd == -1));
641         }
642         else
643         {
644             TCU_CHECK(fd >= 0);
645         }
646 
647         nativeHandle = fd;
648     }
649     else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
650              externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
651     {
652         const vk::VkFenceGetWin32HandleInfoKHR info = {vk::VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR, DE_NULL,
653 
654                                                        fence, externalType};
655         vk::pt::Win32Handle handle(DE_NULL);
656 
657         VK_CHECK(vkd.getFenceWin32HandleKHR(device, &info, &handle));
658 
659         switch (externalType)
660         {
661         case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
662             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
663             break;
664 
665         case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
666             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
667             break;
668 
669         default:
670             DE_FATAL("Unknow external memory handle type");
671         }
672     }
673     else
674         DE_FATAL("Unknow external fence handle type");
675 }
676 
importFence(const vk::DeviceInterface & vkd,const vk::VkDevice device,const vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkFenceImportFlags flags)677 void importFence(const vk::DeviceInterface &vkd, const vk::VkDevice device, const vk::VkFence fence,
678                  vk::VkExternalFenceHandleTypeFlagBits externalType, NativeHandle &handle, vk::VkFenceImportFlags flags)
679 {
680     if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT ||
681         externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
682     {
683         const vk::VkImportFenceFdInfoKHR importInfo = {
684             vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR, DE_NULL, fence, flags, externalType, handle.getFd()};
685 
686         VK_CHECK(vkd.importFenceFdKHR(device, &importInfo));
687         handle.disown();
688     }
689     else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
690              externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
691     {
692         const vk::VkImportFenceWin32HandleInfoKHR importInfo = {
693             vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR,
694             DE_NULL,
695             fence,
696             flags,
697             externalType,
698             handle.getWin32Handle(),
699             (vk::pt::Win32LPCWSTR)DE_NULL};
700 
701         VK_CHECK(vkd.importFenceWin32HandleKHR(device, &importInfo));
702         // \note Importing a fence payload from Windows handles does not transfer ownership of the handle to the Vulkan implementation,
703         //   so we do not disown the handle until after all use has complete.
704     }
705     else
706         DE_FATAL("Unknown fence external handle type");
707 }
708 
createAndImportFence(const vk::DeviceInterface & vkd,const vk::VkDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkFenceImportFlags flags)709 vk::Move<vk::VkFence> createAndImportFence(const vk::DeviceInterface &vkd, const vk::VkDevice device,
710                                            vk::VkExternalFenceHandleTypeFlagBits externalType, NativeHandle &handle,
711                                            vk::VkFenceImportFlags flags)
712 {
713     vk::Move<vk::VkFence> fence(createFence(vkd, device));
714 
715     importFence(vkd, device, *fence, externalType, handle, flags);
716 
717     return fence;
718 }
719 
createExportableSemaphore(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)720 vk::Move<vk::VkSemaphore> createExportableSemaphore(const vk::DeviceInterface &vkd, vk::VkDevice device,
721                                                     vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
722 {
723     const vk::VkExportSemaphoreCreateInfo exportCreateInfo = {vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
724                                                               DE_NULL,
725                                                               (vk::VkExternalSemaphoreHandleTypeFlags)externalType};
726     const vk::VkSemaphoreCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &exportCreateInfo, 0u};
727 
728     return vk::createSemaphore(vkd, device, &createInfo);
729 }
730 
createExportableSemaphoreType(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkSemaphoreType semaphoreType,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)731 vk::Move<vk::VkSemaphore> createExportableSemaphoreType(const vk::DeviceInterface &vkd, vk::VkDevice device,
732                                                         vk::VkSemaphoreType semaphoreType,
733                                                         vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
734 {
735     const vk::VkSemaphoreTypeCreateInfo semaphoreTypeCreateInfo = {
736         vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
737         DE_NULL,
738         semaphoreType,
739         0,
740     };
741     const vk::VkExportSemaphoreCreateInfo exportCreateInfo = {vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
742                                                               &semaphoreTypeCreateInfo,
743                                                               (vk::VkExternalSemaphoreHandleTypeFlags)externalType};
744     const vk::VkSemaphoreCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &exportCreateInfo, 0u};
745 
746     return vk::createSemaphore(vkd, device, &createInfo);
747 }
748 
getSemaphoreFd(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)749 int getSemaphoreFd(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkSemaphore semaphore,
750                    vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
751 {
752     const vk::VkSemaphoreGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, DE_NULL,
753 
754                                               semaphore, externalType};
755     int fd                                 = kInvalidFd;
756 
757     VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
758     TCU_CHECK(fd >= 0);
759 
760     return fd;
761 }
762 
getSemaphoreNative(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & nativeHandle)763 void getSemaphoreNative(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkSemaphore semaphore,
764                         vk::VkExternalSemaphoreHandleTypeFlagBits externalType, NativeHandle &nativeHandle)
765 {
766     if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT ||
767         externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
768     {
769         const vk::VkSemaphoreGetFdInfoKHR info = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, DE_NULL,
770 
771                                                   semaphore, externalType};
772         int fd                                 = kInvalidFd;
773 
774         VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
775 
776         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
777             TCU_CHECK(fd >= -1);
778         else
779             TCU_CHECK(fd >= 0);
780 
781         nativeHandle = fd;
782     }
783     else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA)
784     {
785         const vk::VkSemaphoreGetZirconHandleInfoFUCHSIA info = {
786             vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA, DE_NULL,
787 
788             semaphore, externalType};
789         vk::pt::zx_handle_t zirconHandle(0);
790 
791         VK_CHECK(vkd.getSemaphoreZirconHandleFUCHSIA(device, &info, &zirconHandle));
792         nativeHandle.setZirconHandle(zirconHandle);
793     }
794     else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
795              externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
796     {
797         const vk::VkSemaphoreGetWin32HandleInfoKHR info = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
798                                                            DE_NULL,
799 
800                                                            semaphore, externalType};
801         vk::pt::Win32Handle handle(DE_NULL);
802 
803         VK_CHECK(vkd.getSemaphoreWin32HandleKHR(device, &info, &handle));
804 
805         switch (externalType)
806         {
807         case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:
808             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
809             break;
810 
811         case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT:
812             nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
813             break;
814 
815         default:
816             DE_FATAL("Unknow external memory handle type");
817         }
818     }
819     else
820         DE_FATAL("Unknow external semaphore handle type");
821 }
822 
importSemaphore(const vk::DeviceInterface & vkd,const vk::VkDevice device,const vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkSemaphoreImportFlags flags)823 void importSemaphore(const vk::DeviceInterface &vkd, const vk::VkDevice device, const vk::VkSemaphore semaphore,
824                      vk::VkExternalSemaphoreHandleTypeFlagBits externalType, NativeHandle &handle,
825                      vk::VkSemaphoreImportFlags flags)
826 {
827     if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT ||
828         externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
829     {
830         const vk::VkImportSemaphoreFdInfoKHR importInfo = {vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
831                                                            DE_NULL,
832                                                            semaphore,
833                                                            flags,
834                                                            externalType,
835                                                            handle.getFd()};
836 
837         VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo));
838         handle.disown();
839     }
840     else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA)
841     {
842         const vk::VkImportSemaphoreZirconHandleInfoFUCHSIA importInfo = {
843             vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA,
844             DE_NULL,
845             semaphore,
846             flags,
847             externalType,
848             handle.getZirconHandle()};
849 
850         VK_CHECK(vkd.importSemaphoreZirconHandleFUCHSIA(device, &importInfo));
851         handle.disown();
852     }
853     else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
854              externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
855     {
856         const vk::VkImportSemaphoreWin32HandleInfoKHR importInfo = {
857             vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
858             DE_NULL,
859             semaphore,
860             flags,
861             externalType,
862             handle.getWin32Handle(),
863             (vk::pt::Win32LPCWSTR)DE_NULL};
864 
865         VK_CHECK(vkd.importSemaphoreWin32HandleKHR(device, &importInfo));
866         // \note Importing a semaphore payload from Windows handles does not transfer ownership of the handle to the Vulkan implementation,
867         //   so we do not disown the handle until after all use has complete.
868     }
869     else
870         DE_FATAL("Unknown semaphore external handle type");
871 }
872 
createAndImportSemaphore(const vk::DeviceInterface & vkd,const vk::VkDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & handle,vk::VkSemaphoreImportFlags flags)873 vk::Move<vk::VkSemaphore> createAndImportSemaphore(const vk::DeviceInterface &vkd, const vk::VkDevice device,
874                                                    vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
875                                                    NativeHandle &handle, vk::VkSemaphoreImportFlags flags)
876 {
877     vk::Move<vk::VkSemaphore> semaphore(createSemaphore(vkd, device));
878 
879     importSemaphore(vkd, device, *semaphore, externalType, handle, flags);
880 
881     return semaphore;
882 }
883 
chooseMemoryType(uint32_t bits)884 uint32_t chooseMemoryType(uint32_t bits)
885 {
886     if (bits == 0)
887         return 0;
888 
889     for (uint32_t memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
890     {
891         if ((bits & (1u << memoryTypeIndex)) != 0)
892             return memoryTypeIndex;
893     }
894 
895     DE_FATAL("No supported memory types");
896     return -1;
897 }
898 
chooseHostVisibleMemoryType(uint32_t bits,const vk::VkPhysicalDeviceMemoryProperties properties)899 uint32_t chooseHostVisibleMemoryType(uint32_t bits, const vk::VkPhysicalDeviceMemoryProperties properties)
900 {
901     DE_ASSERT(bits != 0);
902 
903     for (uint32_t memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
904     {
905         if (((bits & (1u << memoryTypeIndex)) != 0) &&
906             ((properties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0))
907             return memoryTypeIndex;
908     }
909 
910     TCU_THROW(NotSupportedError, "No supported memory type found");
911     return -1;
912 }
913 
getImageMemoryRequirements(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkExternalMemoryHandleTypeFlagBits externalType)914 vk::VkMemoryRequirements getImageMemoryRequirements(const vk::DeviceInterface &vkd, vk::VkDevice device,
915                                                     vk::VkImage image,
916                                                     vk::VkExternalMemoryHandleTypeFlagBits externalType)
917 {
918     if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
919     {
920         return {0u, 0u, 0u};
921     }
922     else
923     {
924         return vk::getImageMemoryRequirements(vkd, device, image);
925     }
926 }
927 
allocateExportableMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize allocationSize,uint32_t memoryTypeIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkBuffer buffer)928 vk::Move<vk::VkDeviceMemory> allocateExportableMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
929                                                       vk::VkDeviceSize allocationSize, uint32_t memoryTypeIndex,
930                                                       vk::VkExternalMemoryHandleTypeFlagBits externalType,
931                                                       vk::VkBuffer buffer)
932 {
933     const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
934                                                              DE_NULL,
935 
936                                                              (vk::VkImage)0, buffer};
937     const vk::VkExportMemoryAllocateInfo exportInfo       = {vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
938                                                        !!buffer ? &dedicatedInfo : DE_NULL,
939                                                              (vk::VkExternalMemoryHandleTypeFlags)externalType};
940     const vk::VkMemoryAllocateInfo info = {vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, &exportInfo, allocationSize,
941                                            memoryTypeIndex};
942     return vk::allocateMemory(vkd, device, &info);
943 }
944 
allocateExportableMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceSize allocationSize,uint32_t memoryTypeIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkImage image)945 vk::Move<vk::VkDeviceMemory> allocateExportableMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
946                                                       vk::VkDeviceSize allocationSize, uint32_t memoryTypeIndex,
947                                                       vk::VkExternalMemoryHandleTypeFlagBits externalType,
948                                                       vk::VkImage image)
949 {
950     const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
951                                                              DE_NULL,
952 
953                                                              image, (vk::VkBuffer)0};
954     const vk::VkExportMemoryAllocateInfo exportInfo       = {vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
955                                                        !!image ? &dedicatedInfo : DE_NULL,
956                                                              (vk::VkExternalMemoryHandleTypeFlags)externalType};
957     const vk::VkMemoryAllocateInfo info = {vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, &exportInfo, allocationSize,
958                                            memoryTypeIndex};
959     return vk::allocateMemory(vkd, device, &info);
960 }
961 
importMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer,vk::VkImage image,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,uint32_t memoryTypeIndex,NativeHandle & handle)962 static vk::Move<vk::VkDeviceMemory> importMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
963                                                  vk::VkBuffer buffer, vk::VkImage image,
964                                                  const vk::VkMemoryRequirements &requirements,
965                                                  vk::VkExternalMemoryHandleTypeFlagBits externalType,
966                                                  uint32_t memoryTypeIndex, NativeHandle &handle)
967 {
968     const bool isDedicated = !!buffer || !!image;
969 
970     DE_ASSERT(!buffer || !image);
971 
972     if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
973         externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
974     {
975         const vk::VkImportMemoryFdInfoKHR importInfo = {vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, DE_NULL,
976                                                         externalType, handle.getFd()};
977         const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
978             vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
979             &importInfo,
980             image,
981             buffer,
982         };
983         const vk::VkMemoryAllocateInfo info = {
984             vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
985             (isDedicated ? (const void *)&dedicatedInfo : (const void *)&importInfo), requirements.size,
986             (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex};
987         vk::Move<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, device, &info));
988 
989         handle.disown();
990 
991         return memory;
992     }
993     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
994     {
995         const vk::VkImportMemoryZirconHandleInfoFUCHSIA importInfo = {
996             vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA, DE_NULL, externalType,
997             handle.getZirconHandle()};
998         const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
999             vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1000             &importInfo,
1001             image,
1002             buffer,
1003         };
1004         const vk::VkMemoryAllocateInfo info = {
1005             vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1006             (isDedicated ? (const void *)&dedicatedInfo : (const void *)&importInfo), requirements.size,
1007             (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex};
1008         vk::Move<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, device, &info));
1009 
1010         handle.disown();
1011 
1012         return memory;
1013     }
1014     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
1015              externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
1016     {
1017         const vk::VkImportMemoryWin32HandleInfoKHR importInfo = {
1018             vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, DE_NULL, externalType, handle.getWin32Handle(),
1019             (vk::pt::Win32LPCWSTR)DE_NULL};
1020         const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
1021             vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1022             &importInfo,
1023             image,
1024             buffer,
1025         };
1026         const vk::VkMemoryAllocateInfo info = {
1027             vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1028             (isDedicated ? (const void *)&dedicatedInfo : (const void *)&importInfo), requirements.size,
1029             (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex};
1030         vk::Move<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, device, &info));
1031 
1032         // The handle's owned reference must also be released. Do not discard the handle below.
1033         if (externalType != vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)
1034             handle.disown();
1035 
1036         return memory;
1037     }
1038     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
1039     {
1040         AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
1041         if (!ahbApi)
1042         {
1043             TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
1044         }
1045 
1046         uint32_t ahbFormat = 0;
1047         ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, DE_NULL, DE_NULL);
1048         DE_ASSERT(ahbApi->ahbFormatIsBlob(ahbFormat) || image != 0);
1049 
1050         vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
1051             vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, DE_NULL, 0u, 0u};
1052 
1053         VK_CHECK(
1054             vkd.getAndroidHardwareBufferPropertiesANDROID(device, handle.getAndroidHardwareBuffer(), &ahbProperties));
1055 
1056         vk::VkImportAndroidHardwareBufferInfoANDROID importInfo = {
1057             vk::VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, DE_NULL,
1058             handle.getAndroidHardwareBuffer()};
1059         const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
1060             vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
1061             &importInfo,
1062             image,
1063             buffer,
1064         };
1065         const vk::VkMemoryAllocateInfo info = {
1066             vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1067             (isDedicated ? (const void *)&dedicatedInfo : (const void *)&importInfo), ahbProperties.allocationSize,
1068             (memoryTypeIndex == ~0U) ? chooseMemoryType(ahbProperties.memoryTypeBits) : memoryTypeIndex};
1069         vk::Move<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, device, &info));
1070 
1071         return memory;
1072     }
1073     else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT)
1074     {
1075         DE_ASSERT(memoryTypeIndex != ~0U);
1076 
1077         const vk::VkImportMemoryHostPointerInfoEXT importInfo = {
1078             vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, DE_NULL, externalType, handle.getHostPtr()};
1079         const vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
1080             vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1081             &importInfo,
1082             image,
1083             buffer,
1084         };
1085         const vk::VkMemoryAllocateInfo info = {vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1086                                                (isDedicated ? (const void *)&dedicatedInfo : (const void *)&importInfo),
1087                                                requirements.size, memoryTypeIndex};
1088         vk::Move<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, device, &info));
1089 
1090         return memory;
1091     }
1092     else
1093     {
1094         DE_FATAL("Unknown external memory type");
1095         return vk::Move<vk::VkDeviceMemory>();
1096     }
1097 }
1098 
importMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,uint32_t memoryTypeIndex,NativeHandle & handle)1099 vk::Move<vk::VkDeviceMemory> importMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
1100                                           const vk::VkMemoryRequirements &requirements,
1101                                           vk::VkExternalMemoryHandleTypeFlagBits externalType, uint32_t memoryTypeIndex,
1102                                           NativeHandle &handle)
1103 {
1104     return importMemory(vkd, device, (vk::VkBuffer)0, (vk::VkImage)0, requirements, externalType, memoryTypeIndex,
1105                         handle);
1106 }
1107 
importDedicatedMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,uint32_t memoryTypeIndex,NativeHandle & handle)1108 vk::Move<vk::VkDeviceMemory> importDedicatedMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
1109                                                    vk::VkBuffer buffer, const vk::VkMemoryRequirements &requirements,
1110                                                    vk::VkExternalMemoryHandleTypeFlagBits externalType,
1111                                                    uint32_t memoryTypeIndex, NativeHandle &handle)
1112 {
1113     return importMemory(vkd, device, buffer, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle);
1114 }
1115 
importDedicatedMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,const vk::VkMemoryRequirements & requirements,vk::VkExternalMemoryHandleTypeFlagBits externalType,uint32_t memoryTypeIndex,NativeHandle & handle)1116 vk::Move<vk::VkDeviceMemory> importDedicatedMemory(const vk::DeviceInterface &vkd, vk::VkDevice device,
1117                                                    vk::VkImage image, const vk::VkMemoryRequirements &requirements,
1118                                                    vk::VkExternalMemoryHandleTypeFlagBits externalType,
1119                                                    uint32_t memoryTypeIndex, NativeHandle &handle)
1120 {
1121     return importMemory(vkd, device, (vk::VkBuffer)0, image, requirements, externalType, memoryTypeIndex, handle);
1122 }
1123 
createExternalBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkDeviceSize size,vk::VkBufferCreateFlags createFlags,vk::VkBufferUsageFlags usageFlags)1124 vk::Move<vk::VkBuffer> createExternalBuffer(const vk::DeviceInterface &vkd, vk::VkDevice device,
1125                                             uint32_t queueFamilyIndex,
1126                                             vk::VkExternalMemoryHandleTypeFlagBits externalType, vk::VkDeviceSize size,
1127                                             vk::VkBufferCreateFlags createFlags, vk::VkBufferUsageFlags usageFlags)
1128 {
1129     const vk::VkExternalMemoryBufferCreateInfo externalCreateInfo = {
1130         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, DE_NULL,
1131         (vk::VkExternalMemoryHandleTypeFlags)externalType};
1132     const vk::VkBufferCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1133                                                &externalCreateInfo,
1134                                                createFlags,
1135                                                size,
1136                                                usageFlags,
1137                                                vk::VK_SHARING_MODE_EXCLUSIVE,
1138                                                1u,
1139                                                &queueFamilyIndex};
1140 
1141     return vk::createBuffer(vkd, device, &createInfo);
1142 }
1143 
createExternalImage(const vk::DeviceInterface & vkd,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkFormat format,uint32_t width,uint32_t height,vk::VkImageTiling tiling,vk::VkImageCreateFlags createFlags,vk::VkImageUsageFlags usageFlags,uint32_t mipLevels,uint32_t arrayLayers)1144 vk::Move<vk::VkImage> createExternalImage(const vk::DeviceInterface &vkd, vk::VkDevice device,
1145                                           uint32_t queueFamilyIndex,
1146                                           vk::VkExternalMemoryHandleTypeFlagBits externalType, vk::VkFormat format,
1147                                           uint32_t width, uint32_t height, vk::VkImageTiling tiling,
1148                                           vk::VkImageCreateFlags createFlags, vk::VkImageUsageFlags usageFlags,
1149                                           uint32_t mipLevels, uint32_t arrayLayers)
1150 {
1151     if (createFlags & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT && arrayLayers < 6u)
1152         arrayLayers = 6u;
1153 
1154     const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
1155         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, DE_NULL,
1156         (vk::VkExternalMemoryHandleTypeFlags)externalType};
1157     const vk::VkImageCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1158                                               &externalCreateInfo,
1159                                               createFlags,
1160                                               vk::VK_IMAGE_TYPE_2D,
1161                                               format,
1162                                               {
1163                                                   width,
1164                                                   height,
1165                                                   1u,
1166                                               },
1167                                               mipLevels,
1168                                               arrayLayers,
1169                                               vk::VK_SAMPLE_COUNT_1_BIT,
1170                                               tiling,
1171                                               usageFlags,
1172                                               vk::VK_SHARING_MODE_EXCLUSIVE,
1173                                               1,
1174                                               &queueFamilyIndex,
1175                                               vk::VK_IMAGE_LAYOUT_UNDEFINED};
1176 
1177     return vk::createImage(vkd, device, &createInfo);
1178 }
1179 
getPhysicalDeviceExternalMemoryHostProperties(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)1180 vk::VkPhysicalDeviceExternalMemoryHostPropertiesEXT getPhysicalDeviceExternalMemoryHostProperties(
1181     const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice)
1182 {
1183     vk::VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalProps = {
1184         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
1185         DE_NULL,
1186         0u,
1187     };
1188 
1189     vk::VkPhysicalDeviceProperties2 props2;
1190     deMemset(&props2, 0, sizeof(props2));
1191     props2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1192     props2.pNext = &externalProps;
1193 
1194     vki.getPhysicalDeviceProperties2(physicalDevice, &props2);
1195 
1196     return externalProps;
1197 }
1198 
1199 } // namespace ExternalMemoryUtil
1200 } // namespace vkt
1201 
1202 #endif // CTS_USES_VULKANSC
1203