Merge vk-gl-cts/opengl-cts-4.6.0 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / vktExternalMemoryUtil.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * \brief Vulkan external memory utilities
20  *//*--------------------------------------------------------------------*/
21
22 #include "vktExternalMemoryUtil.hpp"
23
24 #include "vkQueryUtil.hpp"
25
26 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
27 #       include <unistd.h>
28 #       include <fcntl.h>
29 #       include <errno.h>
30 #       include <sys/types.h>
31 #       include <sys/socket.h>
32 #endif
33
34 #if (DE_OS == DE_OS_WIN32)
35 #       define WIN32_LEAN_AND_MEAN
36 #       include <windows.h>
37 #endif
38
39 namespace vkt
40 {
41 namespace ExternalMemoryUtil
42 {
43 namespace
44 {
45 deUint32 chooseMemoryType (deUint32 bits)
46 {
47         DE_ASSERT(bits != 0);
48
49         for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
50         {
51                 if ((bits & (1u << memoryTypeIndex)) != 0)
52                         return memoryTypeIndex;
53         }
54
55         DE_FATAL("No supported memory types");
56         return -1;
57 }
58
59 } // anonymous
60
61 NativeHandle::NativeHandle (void)
62         : m_fd                          (-1)
63         , m_win32HandleType     (WIN32HANDLETYPE_LAST)
64         , m_win32Handle         (DE_NULL)
65 {
66 }
67
68 NativeHandle::NativeHandle (const NativeHandle& other)
69         : m_fd                          (-1)
70         , m_win32HandleType     (WIN32HANDLETYPE_LAST)
71         , m_win32Handle         (DE_NULL)
72 {
73         if (other.m_fd >= 0)
74         {
75 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
76                 DE_ASSERT(!other.m_win32Handle.internal);
77                 m_fd = dup(other.m_fd);
78                 TCU_CHECK(m_fd >= 0);
79 #else
80                 DE_FATAL("Platform doesn't support file descriptors");
81 #endif
82         }
83         else if (other.m_win32Handle.internal)
84         {
85 #if (DE_OS == DE_OS_WIN32)
86                 m_win32HandleType = other.m_win32HandleType;
87
88                 switch (other.m_win32HandleType)
89                 {
90                         case WIN32HANDLETYPE_NT:
91                         {
92                                 DE_ASSERT(other.m_fd == -1);
93
94                                 const HANDLE process = ::GetCurrentProcess();
95                                 ::DuplicateHandle(process, other.m_win32Handle.internal, process, &m_win32Handle.internal, 0, TRUE, DUPLICATE_SAME_ACCESS);
96
97                                 break;
98                         }
99
100                         case WIN32HANDLETYPE_KMT:
101                         {
102                                 m_win32Handle = other.m_win32Handle;
103                                 break;
104                         }
105
106                         default:
107                                 DE_FATAL("Unknown win32 handle type");
108                 }
109 #else
110                 DE_FATAL("Platform doesn't support win32 handles");
111 #endif
112         }
113         else
114                 DE_FATAL("Native handle can't be duplicated");
115 }
116
117 NativeHandle::NativeHandle (int fd)
118         : m_fd                          (fd)
119         , m_win32HandleType     (WIN32HANDLETYPE_LAST)
120         , m_win32Handle         (DE_NULL)
121 {
122 }
123
124 NativeHandle::NativeHandle (Win32HandleType handleType, vk::pt::Win32Handle handle)
125         : m_fd                          (-1)
126         , m_win32HandleType     (handleType)
127         , m_win32Handle         (handle)
128 {
129 }
130
131 NativeHandle::~NativeHandle (void)
132 {
133         reset();
134 }
135
136 void NativeHandle::reset (void)
137 {
138         if (m_fd >= 0)
139         {
140 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
141                 DE_ASSERT(!m_win32Handle.internal);
142                 ::close(m_fd);
143 #else
144                 DE_FATAL("Platform doesn't support file descriptors");
145 #endif
146         }
147
148         if (m_win32Handle.internal)
149         {
150 #if (DE_OS == DE_OS_WIN32)
151                 switch (m_win32HandleType)
152                 {
153                         case WIN32HANDLETYPE_NT:
154                                 DE_ASSERT(m_fd == -1);
155                                 ::CloseHandle((HANDLE)m_win32Handle.internal);
156                                 break;
157
158                         case WIN32HANDLETYPE_KMT:
159                                 break;
160
161                         default:
162                                 DE_FATAL("Unknown win32 handle type");
163                 }
164 #else
165                 DE_FATAL("Platform doesn't support win32 handles");
166 #endif
167         }
168
169         m_fd                            = -1;
170         m_win32Handle           = vk::pt::Win32Handle(DE_NULL);
171         m_win32HandleType       = WIN32HANDLETYPE_LAST;
172 }
173
174 NativeHandle& NativeHandle::operator= (int fd)
175 {
176         reset();
177
178         m_fd = fd;
179
180         return *this;
181 }
182
183 void NativeHandle::setWin32Handle (Win32HandleType type, vk::pt::Win32Handle handle)
184 {
185         reset();
186
187         m_win32HandleType       = type;
188         m_win32Handle           = handle;
189 }
190
191 void NativeHandle::disown (void)
192 {
193         m_fd = -1;
194         m_win32Handle = vk::pt::Win32Handle(DE_NULL);
195 }
196
197 vk::pt::Win32Handle NativeHandle::getWin32Handle (void) const
198 {
199         DE_ASSERT(m_fd == -1);
200         return m_win32Handle;
201 }
202
203 int NativeHandle::getFd (void) const
204 {
205         DE_ASSERT(!m_win32Handle.internal);
206
207         return m_fd;
208 }
209
210 const char* externalSemaphoreTypeToName (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR type)
211 {
212         switch (type)
213         {
214                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
215                         return "opaque_fd";
216
217                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
218                         return "opaque_win32";
219
220                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
221                         return "opaque_win32_kmt";
222
223                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR:
224                         return "d3d12_fenc";
225
226                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
227                         return "sync_fd";
228
229                 default:
230                         DE_FATAL("Unknown external semaphore type");
231                         return DE_NULL;
232         }
233 }
234
235 const char* externalFenceTypeToName (vk::VkExternalFenceHandleTypeFlagBitsKHR type)
236 {
237         switch (type)
238         {
239                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
240                         return "opaque_fd";
241
242                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
243                         return "opaque_win32";
244
245                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
246                         return "opaque_win32_kmt";
247
248                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
249                         return "sync_fd";
250
251                 default:
252                         DE_FATAL("Unknown external fence type");
253                         return DE_NULL;
254         }
255 }
256
257 const char* externalMemoryTypeToName (vk::VkExternalMemoryHandleTypeFlagBitsKHR type)
258 {
259         switch (type)
260         {
261                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
262                         return "opaque_fd";
263
264                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
265                         return "opaque_win32";
266
267                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
268                         return "opaque_win32_kmt";
269
270                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR:
271                         return "d3d11_texture";
272
273                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR:
274                         return "d3d11_texture_kmt";
275
276                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR:
277                         return "d3d12_heap";
278
279                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR:
280                         return "d3d12_resource";
281
282                 default:
283                         DE_FATAL("Unknown external memory type");
284                         return DE_NULL;
285         }
286 }
287
288 bool isSupportedPermanence (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR        type,
289                                                         Permanence                                                                              permanence)
290 {
291         switch (type)
292         {
293                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
294                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
295                         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
296
297                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
298                         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
299
300                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
301                         return permanence == PERMANENCE_TEMPORARY;
302
303                 default:
304                         DE_FATAL("Unknown external semaphore type");
305                         return false;
306         }
307 }
308
309 Transference getHandelTypeTransferences (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR type)
310 {
311         switch (type)
312         {
313                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
314                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
315                         return TRANSFERENCE_REFERENCE;
316
317                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
318                         return TRANSFERENCE_REFERENCE;
319
320                 case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
321                         return TRANSFERENCE_COPY;
322
323                 default:
324                         DE_FATAL("Unknown external semaphore type");
325                         return TRANSFERENCE_REFERENCE;
326         }
327 }
328
329 bool isSupportedPermanence (vk::VkExternalFenceHandleTypeFlagBitsKHR    type,
330                                                         Permanence                                                                      permanence)
331 {
332         switch (type)
333         {
334                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
335                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
336                         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
337
338                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
339                         return permanence == PERMANENCE_PERMANENT || permanence == PERMANENCE_TEMPORARY;
340
341                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
342                         return permanence == PERMANENCE_TEMPORARY;
343
344                 default:
345                         DE_FATAL("Unknown external fence type");
346                         return false;
347         }
348 }
349
350 Transference getHandelTypeTransferences (vk::VkExternalFenceHandleTypeFlagBitsKHR type)
351 {
352         switch (type)
353         {
354                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
355                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
356                         return TRANSFERENCE_REFERENCE;
357
358                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
359                         return TRANSFERENCE_REFERENCE;
360
361                 case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR:
362                         return TRANSFERENCE_COPY;
363
364                 default:
365                         DE_FATAL("Unknown external fence type");
366                         return TRANSFERENCE_REFERENCE;
367         }
368 }
369
370 int getMemoryFd (const vk::DeviceInterface&                                     vkd,
371                                  vk::VkDevice                                                           device,
372                                  vk::VkDeviceMemory                                                     memory,
373                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType)
374 {
375         const vk::VkMemoryGetFdInfoKHR  info    =
376         {
377                 vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
378                 DE_NULL,
379
380                 memory,
381                 externalType
382         };
383         int                                                             fd              = -1;
384
385         VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
386         TCU_CHECK(fd >= 0);
387
388         return fd;
389 }
390
391 void getMemoryNative (const vk::DeviceInterface&                                        vkd,
392                                                  vk::VkDevice                                                           device,
393                                                  vk::VkDeviceMemory                                                     memory,
394                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
395                                                  NativeHandle&                                                          nativeHandle)
396 {
397         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
398         {
399                 const vk::VkMemoryGetFdInfoKHR  info    =
400                 {
401                         vk::VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
402                         DE_NULL,
403
404                         memory,
405                         externalType
406                 };
407                 int                                                             fd              = -1;
408
409                 VK_CHECK(vkd.getMemoryFdKHR(device, &info, &fd));
410                 TCU_CHECK(fd >= 0);
411                 nativeHandle = fd;
412         }
413         else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
414                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
415         {
416                 const vk::VkMemoryGetWin32HandleInfoKHR info    =
417                 {
418                         vk::VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
419                         DE_NULL,
420
421                         memory,
422                         externalType
423                 };
424                 vk::pt::Win32Handle                                             handle  (DE_NULL);
425
426                 VK_CHECK(vkd.getMemoryWin32HandleKHR(device, &info, &handle));
427
428                 switch (externalType)
429                 {
430                         case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
431                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
432                                 break;
433
434                         case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
435                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
436                                 break;
437
438                         default:
439                                 DE_FATAL("Unknow external memory handle type");
440                 }
441         }
442         else
443                 DE_FATAL("Unknow external memory handle type");
444 }
445
446 vk::Move<vk::VkFence> createExportableFence (const vk::DeviceInterface&                                 vkd,
447                                                                                          vk::VkDevice                                                           device,
448                                                                                          vk::VkExternalFenceHandleTypeFlagBitsKHR       externalType)
449 {
450         const vk::VkExportFenceCreateInfoKHR    exportCreateInfo        =
451         {
452                 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR,
453                 DE_NULL,
454                 (vk::VkExternalFenceHandleTypeFlagsKHR)externalType
455         };
456         const vk::VkFenceCreateInfo                             createInfo                      =
457         {
458                 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
459                 &exportCreateInfo,
460                 0u
461         };
462
463         return vk::createFence(vkd, device, &createInfo);
464 }
465
466 int getFenceFd (const vk::DeviceInterface&                                      vkd,
467                                 vk::VkDevice                                                            device,
468                                 vk::VkFence                                                                     fence,
469                                 vk::VkExternalFenceHandleTypeFlagBitsKHR        externalType)
470 {
471         const vk::VkFenceGetFdInfoKHR   info    =
472         {
473                 vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
474                 DE_NULL,
475
476                 fence,
477                 externalType
478         };
479         int                                                             fd      = -1;
480
481         VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
482         TCU_CHECK(fd >= 0);
483
484         return fd;
485 }
486
487 void getFenceNative (const vk::DeviceInterface&                                 vkd,
488                                          vk::VkDevice                                                           device,
489                                          vk::VkFence                                                            fence,
490                                          vk::VkExternalFenceHandleTypeFlagBitsKHR       externalType,
491                                          NativeHandle&                                                          nativeHandle)
492 {
493         if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
494                 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
495         {
496                 const vk::VkFenceGetFdInfoKHR   info    =
497                 {
498                         vk::VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
499                         DE_NULL,
500
501                         fence,
502                         externalType
503                 };
504                 int                                                             fd      = -1;
505
506                 VK_CHECK(vkd.getFenceFdKHR(device, &info, &fd));
507                 TCU_CHECK(fd >= 0);
508                 nativeHandle = fd;
509         }
510         else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
511                 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
512         {
513                 const vk::VkFenceGetWin32HandleInfoKHR  info    =
514                 {
515                         vk::VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR,
516                         DE_NULL,
517
518                         fence,
519                         externalType
520                 };
521                 vk::pt::Win32Handle                                             handle  (DE_NULL);
522
523                 VK_CHECK(vkd.getFenceWin32HandleKHR(device, &info, &handle));
524
525                 switch (externalType)
526                 {
527                         case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
528                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
529                                 break;
530
531                         case vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
532                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
533                                 break;
534
535                         default:
536                                 DE_FATAL("Unknow external memory handle type");
537                 }
538         }
539         else
540                 DE_FATAL("Unknow external fence handle type");
541 }
542
543 void importFence (const vk::DeviceInterface&                            vkd,
544                                   const vk::VkDevice                                            device,
545                                   const vk::VkFence                                                     fence,
546                                   vk::VkExternalFenceHandleTypeFlagBitsKHR      externalType,
547                                   NativeHandle&                                                         handle,
548                                   vk::VkFenceImportFlagsKHR                                     flags)
549 {
550         if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
551                 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
552         {
553                 const vk::VkImportFenceFdInfoKHR        importInfo      =
554                 {
555                         vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
556                         DE_NULL,
557                         fence,
558                         flags,
559                         externalType,
560                         handle.getFd()
561                 };
562
563                 VK_CHECK(vkd.importFenceFdKHR(device, &importInfo));
564                 handle.disown();
565         }
566         else if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
567                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
568         {
569                 const vk::VkImportFenceWin32HandleInfoKHR       importInfo      =
570                 {
571                         vk::VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR,
572                         DE_NULL,
573                         fence,
574                         flags,
575                         externalType,
576                         handle.getWin32Handle(),
577                         DE_NULL
578                 };
579
580                 VK_CHECK(vkd.importFenceWin32HandleKHR(device, &importInfo));
581                 // \note File descriptors and win32 handles behave differently, but this call wil make it seem like they would behave in same way
582                 handle.reset();
583         }
584         else
585                 DE_FATAL("Unknown fence external handle type");
586 }
587
588 vk::Move<vk::VkFence> createAndImportFence (const vk::DeviceInterface&                                  vkd,
589                                                                                         const vk::VkDevice                                                      device,
590                                                                                         vk::VkExternalFenceHandleTypeFlagBitsKHR        externalType,
591                                                                                         NativeHandle&                                                           handle,
592                                                                                         vk::VkFenceImportFlagsKHR                                       flags)
593 {
594         vk::Move<vk::VkFence>   fence   (createFence(vkd, device));
595
596         importFence(vkd, device, *fence, externalType, handle, flags);
597
598         return fence;
599 }
600
601 vk::Move<vk::VkSemaphore> createExportableSemaphore (const vk::DeviceInterface&                                         vkd,
602                                                                                                          vk::VkDevice                                                                   device,
603                                                                                                          vk::VkExternalSemaphoreHandleTypeFlagBitsKHR   externalType)
604 {
605         const vk::VkExportSemaphoreCreateInfoKHR        exportCreateInfo        =
606         {
607                 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR,
608                 DE_NULL,
609                 (vk::VkExternalSemaphoreHandleTypeFlagsKHR)externalType
610         };
611         const vk::VkSemaphoreCreateInfo                         createInfo                      =
612         {
613                 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
614                 &exportCreateInfo,
615                 0u
616         };
617
618         return vk::createSemaphore(vkd, device, &createInfo);
619 }
620
621 int getSemaphoreFd (const vk::DeviceInterface&                                          vkd,
622                                         vk::VkDevice                                                                    device,
623                                         vk::VkSemaphore                                                                 semaphore,
624                                         vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    externalType)
625 {
626         const vk::VkSemaphoreGetFdInfoKHR       info    =
627         {
628                 vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
629                 DE_NULL,
630
631                 semaphore,
632                 externalType
633         };
634         int                                                                             fd      = -1;
635
636         VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
637         TCU_CHECK(fd >= 0);
638
639         return fd;
640 }
641
642 void getSemaphoreNative (const vk::DeviceInterface&                                             vkd,
643                                                  vk::VkDevice                                                                   device,
644                                                  vk::VkSemaphore                                                                semaphore,
645                                                  vk::VkExternalSemaphoreHandleTypeFlagBitsKHR   externalType,
646                                                  NativeHandle&                                                                  nativeHandle)
647 {
648         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
649                 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
650         {
651                 const vk::VkSemaphoreGetFdInfoKHR       info    =
652                 {
653                         vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
654                         DE_NULL,
655
656                         semaphore,
657                         externalType
658                 };
659                 int                                                                             fd      = -1;
660
661                 VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd));
662                 TCU_CHECK(fd >= 0);
663                 nativeHandle = fd;
664         }
665         else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
666                 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
667         {
668                 const vk::VkSemaphoreGetWin32HandleInfoKHR      info    =
669                 {
670                         vk::VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
671                         DE_NULL,
672
673                         semaphore,
674                         externalType
675                 };
676                 vk::pt::Win32Handle                                                     handle  (DE_NULL);
677
678                 VK_CHECK(vkd.getSemaphoreWin32HandleKHR(device, &info, &handle));
679
680                 switch (externalType)
681                 {
682                         case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR:
683                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_NT, handle);
684                                 break;
685
686                         case vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR:
687                                 nativeHandle.setWin32Handle(NativeHandle::WIN32HANDLETYPE_KMT, handle);
688                                 break;
689
690                         default:
691                                 DE_FATAL("Unknow external memory handle type");
692                 }
693         }
694         else
695                 DE_FATAL("Unknow external semaphore handle type");
696 }
697
698 void importSemaphore (const vk::DeviceInterface&                                        vkd,
699                                           const vk::VkDevice                                                    device,
700                                           const vk::VkSemaphore                                                 semaphore,
701                                           vk::VkExternalSemaphoreHandleTypeFlagBitsKHR  externalType,
702                                           NativeHandle&                                                                 handle,
703                                           vk::VkSemaphoreImportFlagsKHR                                 flags)
704 {
705         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
706                 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
707         {
708                 const vk::VkImportSemaphoreFdInfoKHR    importInfo      =
709                 {
710                         vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
711                         DE_NULL,
712                         semaphore,
713                         flags,
714                         externalType,
715                         handle.getFd()
716                 };
717
718                 VK_CHECK(vkd.importSemaphoreFdKHR(device, &importInfo));
719                 handle.disown();
720         }
721         else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
722                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
723         {
724                 const vk::VkImportSemaphoreWin32HandleInfoKHR   importInfo      =
725                 {
726                         vk::VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
727                         DE_NULL,
728                         semaphore,
729                         flags,
730                         externalType,
731                         handle.getWin32Handle(),
732                         DE_NULL
733                 };
734
735                 VK_CHECK(vkd.importSemaphoreWin32HandleKHR(device, &importInfo));
736                 // \note File descriptors and win32 handles behave differently, but this call wil make it seem like they would behave in same way
737                 handle.reset();
738         }
739         else
740                 DE_FATAL("Unknown semaphore external handle type");
741 }
742
743 vk::Move<vk::VkSemaphore> createAndImportSemaphore (const vk::DeviceInterface&                                          vkd,
744                                                                                                         const vk::VkDevice                                                              device,
745                                                                                                         vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    externalType,
746                                                                                                         NativeHandle&                                                                   handle,
747                                                                                                         vk::VkSemaphoreImportFlagsKHR                                   flags)
748 {
749         vk::Move<vk::VkSemaphore>       semaphore       (createSemaphore(vkd, device));
750
751         importSemaphore(vkd, device, *semaphore, externalType, handle, flags);
752
753         return semaphore;
754 }
755
756 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface&                                       vkd,
757                                                                                                            vk::VkDevice                                                                 device,
758                                                                                                            const vk::VkMemoryRequirements&                              requirements,
759                                                                                                            vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
760                                                                                                            vk::VkBuffer                                                                 buffer,
761                                                                                                            deUint32&                                    exportedMemoryTypeIndex)
762 {
763         exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
764         const vk::VkMemoryDedicatedAllocateInfoKHR      dedicatedInfo   =
765         {
766                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
767                 DE_NULL,
768
769                 (vk::VkImage)0,
770                 buffer
771         };
772         const vk::VkExportMemoryAllocateInfoKHR exportInfo      =
773         {
774                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
775                 !!buffer ? &dedicatedInfo : DE_NULL,
776                 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
777         };
778         const vk::VkMemoryAllocateInfo                  info            =
779         {
780                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
781                 &exportInfo,
782                 requirements.size,
783                 exportedMemoryTypeIndex
784         };
785         return vk::allocateMemory(vkd, device, &info);
786 }
787
788 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::DeviceInterface&                                       vkd,
789                                                                                                            vk::VkDevice                                                                 device,
790                                                                                                            const vk::VkMemoryRequirements&                              requirements,
791                                                                                                            vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
792                                                                                                            vk::VkImage                                                                  image,
793                                                                                                            deUint32&                                    exportedMemoryTypeIndex)
794 {
795         exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
796         const vk::VkMemoryDedicatedAllocateInfoKHR      dedicatedInfo   =
797         {
798                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
799                 DE_NULL,
800
801                 image,
802                 (vk::VkBuffer)0
803         };
804         const vk::VkExportMemoryAllocateInfoKHR exportInfo      =
805         {
806                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
807                 !!image ? &dedicatedInfo : DE_NULL,
808                 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
809         };
810         const vk::VkMemoryAllocateInfo                  info            =
811         {
812                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
813                 &exportInfo,
814                 requirements.size,
815                 exportedMemoryTypeIndex
816         };
817         return vk::allocateMemory(vkd, device, &info);
818 }
819
820 vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::InstanceInterface&                                     vki,
821                                                                                                            vk::VkPhysicalDevice                                                 physicalDevice,
822                                                                                                            const vk::DeviceInterface&                                   vkd,
823                                                                                                            vk::VkDevice                                                                 device,
824                                                                                                            const vk::VkMemoryRequirements&                              requirements,
825                                                                                                            vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
826                                                                                                            bool                                                                                 hostVisible,
827                                                                                                            vk::VkBuffer                                                                 buffer,
828                                                                                                            deUint32&                                                                    exportedMemoryTypeIndex)
829 {
830         const vk::VkPhysicalDeviceMemoryProperties properties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);
831
832         for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= requirements.memoryTypeBits; memoryTypeIndex++)
833         {
834                 if (((requirements.memoryTypeBits & (1u << memoryTypeIndex)) != 0)
835                         && (((properties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == hostVisible))
836                 {
837                         const vk::VkMemoryDedicatedAllocateInfoKHR      dedicatedInfo   =
838                         {
839                                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
840                                 DE_NULL,
841
842                                 (vk::VkImage)0,
843                                 buffer
844                         };
845                         const vk::VkExportMemoryAllocateInfoKHR exportInfo      =
846                         {
847                                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
848                                 !!buffer ? &dedicatedInfo : DE_NULL,
849                                 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
850                         };
851                         const vk::VkMemoryAllocateInfo                  info            =
852                         {
853                                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
854                                 &exportInfo,
855                                 requirements.size,
856                                 memoryTypeIndex
857                         };
858
859                         exportedMemoryTypeIndex = memoryTypeIndex;
860                         return vk::allocateMemory(vkd, device, &info);
861                 }
862         }
863
864         TCU_THROW(NotSupportedError, "No supported memory type found");
865 }
866
867 static vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface&                            vkd,
868                                                                                                   vk::VkDevice                                                          device,
869                                                                                                   vk::VkBuffer                                                          buffer,
870                                                                                                   vk::VkImage                                                           image,
871                                                                                                   const vk::VkMemoryRequirements&                       requirements,
872                                                                                                   vk::VkExternalMemoryHandleTypeFlagBitsKHR     externalType,
873                                                                                                   deUint32                                                                      memoryTypeIndex,
874                                                                                                   NativeHandle&                                                         handle)
875 {
876         const bool      isDedicated             = !!buffer || !!image;
877
878         DE_ASSERT(!buffer || !image);
879
880         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
881         {
882                 const vk::VkImportMemoryFdInfoKHR                       importInfo              =
883                 {
884                         vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
885                         DE_NULL,
886                         externalType,
887                         handle.getFd()
888                 };
889                 const vk::VkMemoryDedicatedAllocateInfoKHR      dedicatedInfo   =
890                 {
891                         vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
892                         &importInfo,
893                         image,
894                         buffer,
895                 };
896                 const vk::VkMemoryAllocateInfo                          info                    =
897                 {
898                         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
899                         (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
900                         requirements.size,
901                         (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits) : memoryTypeIndex
902                 };
903                 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
904
905                 handle.disown();
906
907                 return memory;
908         }
909         else if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
910                         || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
911         {
912                 const vk::VkImportMemoryWin32HandleInfoKHR      importInfo =
913                 {
914                         vk::VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
915                         DE_NULL,
916                         externalType,
917                         handle.getWin32Handle(),
918                         DE_NULL
919                 };
920                 const vk::VkMemoryDedicatedAllocateInfoKHR      dedicatedInfo   =
921                 {
922                         vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
923                         &importInfo,
924                         image,
925                         buffer,
926                 };
927                 const vk::VkMemoryAllocateInfo                          info                    =
928                 {
929                         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
930                         (isDedicated ? (const void*)&dedicatedInfo : (const void*)&importInfo),
931                         requirements.size,
932                         (memoryTypeIndex == ~0U) ? chooseMemoryType(requirements.memoryTypeBits)  : memoryTypeIndex
933                 };
934                 vk::Move<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, device, &info));
935
936                 handle.disown();
937
938                 return memory;
939         }
940         else
941         {
942                 DE_FATAL("Unknown external memory type");
943                 return vk::Move<vk::VkDeviceMemory>();
944         }
945 }
946
947 vk::Move<vk::VkDeviceMemory> importMemory (const vk::DeviceInterface&                                   vkd,
948                                                                                    vk::VkDevice                                                                 device,
949                                                                                    const vk::VkMemoryRequirements&                              requirements,
950                                                                                    vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
951                                                                                    deUint32                                                                             memoryTypeIndex,
952                                                                                    NativeHandle&                                                                handle)
953 {
954         return importMemory(vkd, device, (vk::VkBuffer)0, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle);
955 }
956
957 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface&                                  vkd,
958                                                                                                         vk::VkDevice                                                            device,
959                                                                                                         vk::VkBuffer                                                            buffer,
960                                                                                                         const vk::VkMemoryRequirements&                         requirements,
961                                                                                                         vk::VkExternalMemoryHandleTypeFlagBitsKHR       externalType,
962                                                                                                         deUint32                                                                        memoryTypeIndex,
963                                                                                                         NativeHandle&                                                           handle)
964 {
965         return importMemory(vkd, device, buffer, (vk::VkImage)0, requirements, externalType, memoryTypeIndex, handle);
966 }
967
968 vk::Move<vk::VkDeviceMemory> importDedicatedMemory (const vk::DeviceInterface&                                  vkd,
969                                                                                                         vk::VkDevice                                                            device,
970                                                                                                         vk::VkImage                                                                     image,
971                                                                                                         const vk::VkMemoryRequirements&                         requirements,
972                                                                                                         vk::VkExternalMemoryHandleTypeFlagBitsKHR       externalType,
973                                                                                                         deUint32                                                                        memoryTypeIndex,
974                                                                                                         NativeHandle&                                                           handle)
975 {
976         return importMemory(vkd, device, (vk::VkBuffer)0, image, requirements, externalType, memoryTypeIndex, handle);
977 }
978
979 vk::Move<vk::VkBuffer> createExternalBuffer (const vk::DeviceInterface&                                 vkd,
980                                                                                          vk::VkDevice                                                           device,
981                                                                                          deUint32                                                                       queueFamilyIndex,
982                                                                                          vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
983                                                                                          vk::VkDeviceSize                                                       size,
984                                                                                          vk::VkBufferCreateFlags                                        createFlags,
985                                                                                          vk::VkBufferUsageFlags                                         usageFlags)
986 {
987         const vk::VkExternalMemoryBufferCreateInfoKHR           externalCreateInfo      =
988         {
989                 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
990                 DE_NULL,
991                 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
992         };
993         const vk::VkBufferCreateInfo                                            createInfo                      =
994         {
995                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
996                 &externalCreateInfo,
997                 createFlags,
998                 size,
999                 usageFlags,
1000                 vk::VK_SHARING_MODE_EXCLUSIVE,
1001                 1u,
1002                 &queueFamilyIndex
1003         };
1004
1005         return vk::createBuffer(vkd, device, &createInfo);
1006 }
1007
1008 vk::Move<vk::VkImage> createExternalImage (const vk::DeviceInterface&                                   vkd,
1009                                                                                    vk::VkDevice                                                                 device,
1010                                                                                    deUint32                                                                             queueFamilyIndex,
1011                                                                                    vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
1012                                                                                    vk::VkFormat                                                                 format,
1013                                                                                    deUint32                                                                             width,
1014                                                                                    deUint32                                                                             height,
1015                                                                                    vk::VkImageTiling                                                    tiling,
1016                                                                                    vk::VkImageCreateFlags                                               createFlags,
1017                                                                                    vk::VkImageUsageFlags                                                usageFlags)
1018 {
1019         const vk::VkExternalMemoryImageCreateInfoKHR            externalCreateInfo      =
1020         {
1021                 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
1022                 DE_NULL,
1023                 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
1024         };
1025         const vk::VkImageCreateInfo                                             createInfo                      =
1026         {
1027                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1028                 &externalCreateInfo,
1029                 createFlags,
1030                 vk::VK_IMAGE_TYPE_2D,
1031                 format,
1032                 { width, height, 1u, },
1033                 1u,
1034                 1u,
1035                 vk::VK_SAMPLE_COUNT_1_BIT,
1036                 tiling,
1037                 usageFlags,
1038                 vk::VK_SHARING_MODE_EXCLUSIVE,
1039                 1,
1040                 &queueFamilyIndex,
1041                 vk::VK_IMAGE_LAYOUT_UNDEFINED
1042         };
1043
1044         return vk::createImage(vkd, device, &createInfo);
1045 }
1046
1047 } // ExternalMemoryUtil
1048 } // vkt