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