13dffec6b6741e613e86c4ef05e7dd1c3dd56760
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiExternalMemoryTests.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 API tests
20  *//*--------------------------------------------------------------------*/
21
22 #include "vktApiExternalMemoryTests.hpp"
23
24 #include "vktTestCaseUtil.hpp"
25 #include "vkRefUtil.hpp"
26 #include "vkDeviceUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkPlatform.hpp"
29 #include "vkMemUtil.hpp"
30
31 #include "tcuTestLog.hpp"
32
33 #include "deUniquePtr.hpp"
34 #include "deStringUtil.hpp"
35 #include "deRandom.hpp"
36
37 #include "deMemory.h"
38
39 #include "vktExternalMemoryUtil.hpp"
40
41 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
42 #       include <unistd.h>
43 #       include <fcntl.h>
44 #       include <errno.h>
45 #       include <sys/types.h>
46 #       include <sys/socket.h>
47 #endif
48
49 #if (DE_OS == DE_OS_WIN32)
50 #       define WIN32_LEAN_AND_MEAN
51 #       include <windows.h>
52 #       include <Dxgi1_2.h>
53 #endif
54
55 using tcu::TestLog;
56 using namespace vkt::ExternalMemoryUtil;
57
58 namespace vkt
59 {
60 namespace api
61 {
62 namespace
63 {
64
65 vk::VkMemoryDedicatedRequirementsKHR getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
66                                                                                                                                          vk::VkDevice                           device,
67                                                                                                                                          vk::VkBuffer                           buffer)
68 {
69         const vk::VkBufferMemoryRequirementsInfo2KHR    requirementInfo                 =
70         {
71                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
72                 DE_NULL,
73                 buffer
74         };
75         vk::VkMemoryDedicatedRequirementsKHR                    dedicatedRequirements   =
76         {
77                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
78                 DE_NULL,
79                 VK_FALSE,
80                 VK_FALSE
81         };
82         vk::VkMemoryRequirements2KHR                                    requirements                    =
83         {
84                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
85                 &dedicatedRequirements,
86                 { 0u, 0u, 0u }
87         };
88
89         vkd.getBufferMemoryRequirements2KHR(device, &requirementInfo, &requirements);
90
91         return dedicatedRequirements;
92 }
93
94 vk::VkMemoryDedicatedRequirementsKHR getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
95                                                                                                                                          vk::VkDevice                           device,
96                                                                                                                                          vk::VkImage                            image)
97 {
98         const vk::VkImageMemoryRequirementsInfo2KHR     requirementInfo                 =
99         {
100                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
101                 DE_NULL,
102                 image
103         };
104         vk::VkMemoryDedicatedRequirementsKHR            dedicatedRequirements   =
105         {
106                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
107                 DE_NULL,
108                 VK_FALSE,
109                 VK_FALSE
110         };
111         vk::VkMemoryRequirements2KHR                            requirements                    =
112         {
113                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
114                 &dedicatedRequirements,
115                 { 0u, 0u, 0u }
116         };
117
118         vkd.getImageMemoryRequirements2KHR(device, &requirementInfo, &requirements);
119
120         return dedicatedRequirements;
121 }
122
123 void writeHostMemory (const vk::DeviceInterface&        vkd,
124                                           vk::VkDevice                                  device,
125                                           vk::VkDeviceMemory                    memory,
126                                           size_t                                                size,
127                                           const void*                                   data)
128 {
129         void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
130
131         deMemcpy(ptr, data, size);
132
133         vkd.unmapMemory(device, memory);
134 }
135
136 void checkHostMemory (const vk::DeviceInterface&        vkd,
137                                           vk::VkDevice                                  device,
138                                           vk::VkDeviceMemory                    memory,
139                                           size_t                                                size,
140                                           const void*                                   data)
141 {
142         void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
143
144         if (deMemCmp(ptr, data, size) != 0)
145                 TCU_FAIL("Memory contents don't match");
146
147         vkd.unmapMemory(device, memory);
148 }
149
150 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
151 {
152         de::Random                              rng             (seed);
153         std::vector<deUint8>    data    (size);
154
155         for (size_t ndx = 0; ndx < size; ndx++)
156         {
157                 data[ndx] = rng.getUint8();
158         }
159
160         return data;
161 }
162
163 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface&   vki,
164                                                                  vk::VkPhysicalDevice                   device,
165                                                                  vk::VkQueueFlags                               requireFlags)
166 {
167         const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
168
169         for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
170         {
171                 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
172                         return queueFamilyIndex;
173         }
174
175         TCU_THROW(NotSupportedError, "Queue type not supported");
176 }
177
178 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface&                                           vkp,
179                                                                                  const vk::VkExternalSemaphoreHandleTypeFlagsKHR        externalSemaphoreTypes,
180                                                                                  const vk::VkExternalMemoryHandleTypeFlagsKHR           externalMemoryTypes,
181                                                                                  const vk::VkExternalFenceHandleTypeFlagsKHR            externalFenceTypes)
182 {
183         std::vector<std::string> instanceExtensions;
184
185         instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
186
187         if (externalSemaphoreTypes != 0)
188                 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
189
190         if (externalMemoryTypes != 0)
191                 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
192
193         if (externalFenceTypes != 0)
194                 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
195
196         try
197         {
198                 return vk::createDefaultInstance(vkp, std::vector<std::string>(), instanceExtensions);
199         }
200         catch (const vk::Error& error)
201         {
202                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
203                         TCU_THROW(NotSupportedError, "Required extensions not supported");
204
205                 throw;
206         }
207 }
208
209 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface&                                               vki,
210                                                                          vk::VkPhysicalDevice                                                           physicalDevice,
211                                                                          const vk::VkExternalSemaphoreHandleTypeFlagsKHR        externalSemaphoreTypes,
212                                                                          const vk::VkExternalMemoryHandleTypeFlagsKHR           externalMemoryTypes,
213                                                                          const vk::VkExternalFenceHandleTypeFlagsKHR            externalFenceTypes,
214                                                                          deUint32                                                                                       queueFamilyIndex,
215                                                                          bool                                                                                           useDedicatedAllocs = false)
216 {
217         std::vector<const char*>        deviceExtensions;
218
219         if ((externalSemaphoreTypes
220                         & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
221                                 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)) != 0)
222         {
223                 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
224         }
225
226         if ((externalFenceTypes
227                         & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
228                                 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)) != 0)
229         {
230                 deviceExtensions.push_back("VK_KHR_external_fence_fd");
231         }
232
233         if (useDedicatedAllocs)
234         {
235                 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
236                 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
237         }
238
239         if ((externalMemoryTypes
240                         & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) != 0)
241         {
242                 deviceExtensions.push_back("VK_KHR_external_memory_fd");
243         }
244
245         if ((externalSemaphoreTypes
246                         & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
247                                 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)) != 0)
248         {
249                 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
250         }
251
252         if ((externalFenceTypes
253                         & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
254                                 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)) != 0)
255         {
256                 deviceExtensions.push_back("VK_KHR_external_fence_win32");
257         }
258
259         if ((externalMemoryTypes
260                         & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
261                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
262                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR
263                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR
264                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR
265                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR)) != 0)
266         {
267                 deviceExtensions.push_back("VK_KHR_external_memory_win32");
268         }
269
270         const float                                                             priority                                = 0.5f;
271         const vk::VkDeviceQueueCreateInfo               queues[]                                =
272         {
273                 {
274                         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
275                         DE_NULL,
276                         0u,
277
278                         queueFamilyIndex,
279                         1u,
280                         &priority
281                 }
282         };
283         const vk::VkDeviceCreateInfo                    deviceCreateInfo                =
284         {
285                 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
286                 DE_NULL,
287                 0u,
288
289                 DE_LENGTH_OF_ARRAY(queues),
290                 queues,
291
292                 0u,
293                 DE_NULL,
294
295                 (deUint32)deviceExtensions.size(),
296                 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
297                 DE_NULL
298         };
299
300         try
301         {
302                 return vk::createDevice(vki, physicalDevice, &deviceCreateInfo);
303         }
304         catch (const vk::Error& error)
305         {
306                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
307                         TCU_THROW(NotSupportedError, "Required extensions not supported");
308
309                 throw;
310         }
311 }
312
313 vk::VkQueue getQueue (const vk::DeviceInterface&        vkd,
314                                           vk::VkDevice                                  device,
315                                           deUint32                                              queueFamilyIndex)
316 {
317         vk::VkQueue queue;
318
319         vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
320
321         return queue;
322 }
323
324 void checkSemaphoreSupport (const vk::InstanceInterface&                                        vki,
325                                                         vk::VkPhysicalDevice                                                    device,
326                                                         vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    externalType)
327 {
328         const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR      info                    =
329         {
330                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
331                 DE_NULL,
332                 externalType
333         };
334         vk::VkExternalSemaphorePropertiesKHR                            properties      =
335         {
336                 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR,
337                 DE_NULL,
338                 0u,
339                 0u,
340                 0u
341         };
342
343         vki.getPhysicalDeviceExternalSemaphorePropertiesKHR(device, &info, &properties);
344
345         if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0)
346                 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
347
348         if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
349                 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
350 }
351
352 void checkFenceSupport (const vk::InstanceInterface&                            vki,
353                                                 vk::VkPhysicalDevice                                            device,
354                                                 vk::VkExternalFenceHandleTypeFlagBitsKHR        externalType)
355 {
356         const vk::VkPhysicalDeviceExternalFenceInfoKHR  info                    =
357         {
358                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR,
359                 DE_NULL,
360                 externalType
361         };
362         vk::VkExternalFencePropertiesKHR                                properties      =
363         {
364                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR,
365                 DE_NULL,
366                 0u,
367                 0u,
368                 0u
369         };
370
371         vki.getPhysicalDeviceExternalFencePropertiesKHR(device, &info, &properties);
372
373         if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR) == 0)
374                 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
375
376         if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
377                 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
378 }
379
380 void checkBufferSupport (const vk::InstanceInterface&                           vki,
381                                                  vk::VkPhysicalDevice                                           device,
382                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
383                                                  vk::VkBufferViewCreateFlags                            createFlag,
384                                                  vk::VkBufferUsageFlags                                         usageFlag,
385                                                  bool                                                                           dedicated)
386 {
387         const vk::VkPhysicalDeviceExternalBufferInfoKHR info                    =
388         {
389                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
390                 DE_NULL,
391
392                 createFlag,
393                 usageFlag,
394                 externalType
395         };
396         vk::VkExternalBufferPropertiesKHR                               properties              =
397         {
398                 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
399                 DE_NULL,
400
401                 { 0u, 0u, 0u }
402         };
403
404         vki.getPhysicalDeviceExternalBufferPropertiesKHR(device, &info, &properties);
405
406         if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
407                 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
408
409         if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
410                 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
411
412         if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
413                 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
414 }
415
416 void checkImageSupport (const vk::InstanceInterface&                            vki,
417                                                  vk::VkPhysicalDevice                                           device,
418                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
419                                                  vk::VkImageViewCreateFlags                                     createFlag,
420                                                  vk::VkImageUsageFlags                                          usageFlag,
421                                                  vk::VkFormat                                                           format,
422                                                  vk::VkImageTiling                                                      tiling,
423                                                  bool                                                                           dedicated)
424 {
425         const vk::VkPhysicalDeviceExternalImageFormatInfoKHR    externalInfo    =
426         {
427                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
428                 DE_NULL,
429                 externalType
430         };
431         const vk::VkPhysicalDeviceImageFormatInfo2KHR                   info                    =
432         {
433                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
434                 &externalInfo,
435
436                 format,
437                 vk::VK_IMAGE_TYPE_2D,
438                 tiling,
439                 usageFlag,
440                 createFlag,
441         };
442         vk::VkExternalImageFormatPropertiesKHR                                  externalProperties      =
443         {
444                 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
445                 DE_NULL,
446                 { 0u, 0u, 0u }
447         };
448         vk::VkImageFormatProperties2KHR                                                 properties                      =
449         {
450                 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
451                 &externalProperties,
452                 {
453                         { 0u, 0u, 0u },
454                         0u,
455                         0u,
456                         0u,
457                         0u
458                 }
459         };
460
461         vki.getPhysicalDeviceImageFormatProperties2KHR(device, &info, &properties);
462
463         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
464                 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
465
466         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
467                 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
468
469         if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
470                 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
471 }
472
473 void submitDummySignal (const vk::DeviceInterface&      vkd,
474                                                 vk::VkQueue                                     queue,
475                                                 vk::VkSemaphore                         semaphore)
476 {
477         const vk::VkSubmitInfo submit =
478         {
479                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
480                 DE_NULL,
481
482                 0u,
483                 DE_NULL,
484                 DE_NULL,
485
486                 0u,
487                 DE_NULL,
488
489                 1u,
490                 &semaphore
491         };
492
493         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
494 }
495
496 void submitDummyWait (const vk::DeviceInterface&        vkd,
497                                           vk::VkQueue                                   queue,
498                                           vk::VkSemaphore                               semaphore)
499 {
500         const vk::VkPipelineStageFlags  stage   = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
501         const vk::VkSubmitInfo                  submit  =
502         {
503                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
504                 DE_NULL,
505
506                 1u,
507                 &semaphore,
508                 &stage,
509
510                 0u,
511                 DE_NULL,
512
513                 0u,
514                 DE_NULL,
515         };
516
517         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
518 }
519
520 void submitDummySignal (const vk::DeviceInterface&      vkd,
521                                                 vk::VkQueue                                     queue,
522                                                 vk::VkFence                                     fence)
523 {
524         const vk::VkSubmitInfo submit =
525         {
526                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
527                 DE_NULL,
528
529                 0u,
530                 DE_NULL,
531                 DE_NULL,
532
533                 0u,
534                 DE_NULL,
535
536                 0u,
537                 DE_NULL
538         };
539
540         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
541 }
542
543 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType)
544 {
545         const vk::PlatformInterface&            vkp                             (context.getPlatformInterface());
546         const vk::Unique<vk::VkInstance>        instance                (createInstance(vkp, externalType, 0u, 0u));
547         const vk::InstanceDriver                        vki                             (vkp, *instance);
548         const vk::VkPhysicalDevice                      device                  (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
549
550         TestLog&                                                        log                             = context.getTestContext().getLog();
551
552         const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR      info                    =
553         {
554                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
555                 DE_NULL,
556                 externalType
557         };
558         vk::VkExternalSemaphorePropertiesKHR                            properties      =
559         {
560                 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR,
561                 DE_NULL,
562                 0u,
563                 0u,
564                 0u
565         };
566
567         vki.getPhysicalDeviceExternalSemaphorePropertiesKHR(device, &info, &properties);
568         log << TestLog::Message << properties << TestLog::EndMessage;
569
570         TCU_CHECK(properties.pNext == DE_NULL);
571         TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR);
572
573         return tcu::TestStatus::pass("Pass");
574 }
575
576 struct SemaphoreTestConfig
577 {
578                                                                                                         SemaphoreTestConfig     (vk::VkExternalSemaphoreHandleTypeFlagBitsKHR   externalType_,
579                                                                                                                                                  Permanence                                                                             permanence_)
580                 : externalType          (externalType_)
581                 , permanence            (permanence_)
582         {
583         }
584
585         vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    externalType;
586         Permanence                                                                              permanence;
587 };
588
589 tcu::TestStatus testSemaphoreWin32Create (Context&                                      context,
590                                                                                   const SemaphoreTestConfig     config)
591 {
592 #if (DE_OS == DE_OS_WIN32)
593         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
594         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
595         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
596         const vk::InstanceDriver                        vki                                     (vkp, *instance);
597         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
598         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
599
600         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
601
602         {
603                 const vk::Unique<vk::VkDevice>                                  device                  (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
604                 const vk::DeviceDriver                                                  vkd                             (vki, *device);
605                 const vk::VkQueue                                                               queue                   (getQueue(vkd, *device, queueFamilyIndex));
606                 const vk::VkExportSemaphoreWin32HandleInfoKHR   win32ExportInfo =
607                 {
608                         vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
609                         DE_NULL,
610
611                         (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
612                         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
613                         DE_NULL
614                 };
615                 const vk::VkExportSemaphoreCreateInfoKHR                exportCreateInfo=
616                 {
617                         vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR,
618                         &win32ExportInfo,
619                         (vk::VkExternalMemoryHandleTypeFlagsKHR)config.externalType
620                 };
621                 const vk::VkSemaphoreCreateInfo                                 createInfo              =
622                 {
623                         vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
624                         &exportCreateInfo,
625                         0u
626                 };
627                 const vk::Unique<vk::VkSemaphore>                               semaphore               (vk::createSemaphore(vkd, *device, &createInfo));
628
629                 if (transference == TRANSFERENCE_COPY)
630                         submitDummySignal(vkd, queue, *semaphore);
631
632                 NativeHandle                                            handleA;
633                 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
634
635                 {
636                         const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
637                         const vk::Unique<vk::VkSemaphore>       semaphoreA      (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
638
639                         if (transference == TRANSFERENCE_COPY)
640                                 submitDummyWait(vkd, queue, *semaphoreA);
641                         else if (transference == TRANSFERENCE_REFERENCE)
642                         {
643                                 submitDummySignal(vkd, queue, *semaphore);
644                                 submitDummyWait(vkd, queue, *semaphoreA);
645                         }
646                         else
647                                 DE_FATAL("Unknown transference.");
648
649                         VK_CHECK(vkd.queueWaitIdle(queue));
650                 }
651
652                 return tcu::TestStatus::pass("Pass");
653         }
654 #else
655         DE_UNREF(context);
656         DE_UNREF(config);
657         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
658 #endif
659 }
660
661 tcu::TestStatus testSemaphoreImportTwice (Context&                                      context,
662                                                                                   const SemaphoreTestConfig     config)
663 {
664         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
665         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
666         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
667         const vk::InstanceDriver                        vki                                     (vkp, *instance);
668         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
669         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
670
671         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
672
673         {
674                 const vk::Unique<vk::VkDevice>          device                  (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
675                 const vk::DeviceDriver                          vkd                             (vki, *device);
676                 const vk::VkQueue                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
677                 const vk::Unique<vk::VkSemaphore>       semaphore               (createExportableSemaphore(vkd, *device, config.externalType));
678
679                 if (transference == TRANSFERENCE_COPY)
680                         submitDummySignal(vkd, queue, *semaphore);
681
682                 NativeHandle                                            handleA;
683                 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
684
685                 {
686                         NativeHandle                                            handleB         (handleA);
687                         const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
688                         const vk::Unique<vk::VkSemaphore>       semaphoreA      (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
689                         const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
690
691                         if (transference == TRANSFERENCE_COPY)
692                                 submitDummyWait(vkd, queue, *semaphoreA);
693                         else if (transference == TRANSFERENCE_REFERENCE)
694                         {
695                                 submitDummySignal(vkd, queue, *semaphoreA);
696                                 submitDummyWait(vkd, queue, *semaphoreB);
697                         }
698                         else
699                                 DE_FATAL("Unknown transference.");
700
701                         VK_CHECK(vkd.queueWaitIdle(queue));
702                 }
703
704                 return tcu::TestStatus::pass("Pass");
705         }
706 }
707
708 tcu::TestStatus testSemaphoreImportReimport (Context&                                   context,
709                                                                                          const SemaphoreTestConfig      config)
710 {
711         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
712         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
713         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
714         const vk::InstanceDriver                        vki                                     (vkp, *instance);
715         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
716         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
717
718         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
719
720         {
721                 const vk::Unique<vk::VkDevice>          device                  (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
722                 const vk::DeviceDriver                          vkd                             (vki, *device);
723                 const vk::VkQueue                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
724
725                 const vk::Unique<vk::VkSemaphore>       semaphoreA              (createExportableSemaphore(vkd, *device, config.externalType));
726
727                 if (transference == TRANSFERENCE_COPY)
728                         submitDummySignal(vkd, queue, *semaphoreA);
729
730                 NativeHandle                                            handleA;
731                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
732
733                 NativeHandle                                            handleB         (handleA);
734                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
735                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
736
737                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
738
739                 if (transference == TRANSFERENCE_COPY)
740                         submitDummyWait(vkd, queue, *semaphoreB);
741                 else if (transference == TRANSFERENCE_REFERENCE)
742                 {
743                         submitDummySignal(vkd, queue, *semaphoreA);
744                         submitDummyWait(vkd, queue, *semaphoreB);
745                 }
746                 else
747                         DE_FATAL("Unknown transference.");
748
749                 VK_CHECK(vkd.queueWaitIdle(queue));
750
751                 return tcu::TestStatus::pass("Pass");
752         }
753 }
754
755 tcu::TestStatus testSemaphoreSignalExportImportWait (Context&                                   context,
756                                                                                                          const SemaphoreTestConfig      config)
757 {
758         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
759         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
760         const vk::InstanceDriver                        vki                                     (vkp, *instance);
761         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
762         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
763
764         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
765
766         {
767                 const vk::Unique<vk::VkDevice>          device                          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
768                 const vk::DeviceDriver                          vkd                                     (vki, *device);
769                 const vk::VkQueue                                       queue                           (getQueue(vkd, *device, queueFamilyIndex));
770                 const vk::Unique<vk::VkSemaphore>       semaphoreA                      (createExportableSemaphore(vkd, *device, config.externalType));
771
772                 submitDummySignal(vkd, queue, *semaphoreA);
773
774                 {
775                         NativeHandle    handle;
776
777                         getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
778
779                         {
780                                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
781                                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
782                                 submitDummyWait(vkd, queue, *semaphoreB);
783
784                                 VK_CHECK(vkd.queueWaitIdle(queue));
785                         }
786                 }
787
788                 return tcu::TestStatus::pass("Pass");
789         }
790 }
791
792 tcu::TestStatus testSemaphoreExportSignalImportWait (Context&                                   context,
793                                                                                                          const SemaphoreTestConfig      config)
794 {
795         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
796         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
797         const vk::InstanceDriver                        vki                                     (vkp, *instance);
798         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
799         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
800         const vk::VkSemaphoreImportFlagsKHR     flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
801
802         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
803         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
804
805         {
806                 const vk::Unique<vk::VkDevice>          device                          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
807                 const vk::DeviceDriver                          vkd                                     (vki, *device);
808                 const vk::VkQueue                                       queue                           (getQueue(vkd, *device, queueFamilyIndex));
809
810                 const vk::Unique<vk::VkSemaphore>       semaphoreA                      (createExportableSemaphore(vkd, *device, config.externalType));
811                 NativeHandle                                            handle;
812
813                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
814
815                 submitDummySignal(vkd, queue, *semaphoreA);
816                 {
817                         {
818                                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
819
820                                 submitDummyWait(vkd, queue, *semaphoreB);
821                                 VK_CHECK(vkd.queueWaitIdle(queue));
822                         }
823                 }
824
825                 return tcu::TestStatus::pass("Pass");
826         }
827 }
828
829 tcu::TestStatus testSemaphoreExportImportSignalWait (Context&                                   context,
830                                                                                                          const SemaphoreTestConfig      config)
831 {
832         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
833         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
834         const vk::InstanceDriver                        vki                                     (vkp, *instance);
835         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
836         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
837
838         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
839         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
840
841         {
842                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
843                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
844                 const vk::DeviceDriver                          vkd                     (vki, *device);
845                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
846
847                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
848                 NativeHandle                                            handle;
849
850                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
851
852                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
853
854                 submitDummySignal(vkd, queue, *semaphoreA);
855                 submitDummyWait(vkd, queue, *semaphoreB);
856
857                 VK_CHECK(vkd.queueWaitIdle(queue));
858
859                 return tcu::TestStatus::pass("Pass");
860         }
861 }
862
863 tcu::TestStatus testSemaphoreSignalImport (Context&                                             context,
864                                                                                    const SemaphoreTestConfig    config)
865 {
866         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
867         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
868         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
869         const vk::InstanceDriver                        vki                                     (vkp, *instance);
870         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
871         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
872
873         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
874
875         {
876                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
877                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
878                 const vk::DeviceDriver                          vkd                     (vki, *device);
879                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
880
881                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
882                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createSemaphore(vkd, *device));
883                 NativeHandle                                            handle;
884
885                 submitDummySignal(vkd, queue, *semaphoreB);
886                 VK_CHECK(vkd.queueWaitIdle(queue));
887
888                 if (transference == TRANSFERENCE_COPY)
889                         submitDummySignal(vkd, queue, *semaphoreA);
890
891                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
892
893                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
894
895                 if (transference == TRANSFERENCE_COPY)
896                         submitDummyWait(vkd, queue, *semaphoreB);
897                 else if (transference == TRANSFERENCE_REFERENCE)
898                 {
899                         submitDummySignal(vkd, queue, *semaphoreA);
900                         submitDummyWait(vkd, queue, *semaphoreB);
901                 }
902                 else
903                         DE_FATAL("Unknown transference.");
904
905                 VK_CHECK(vkd.queueWaitIdle(queue));
906
907                 return tcu::TestStatus::pass("Pass");
908         }
909 }
910
911 tcu::TestStatus testSemaphoreSignalWaitImport (Context&                                         context,
912                                                                                            const SemaphoreTestConfig    config)
913 {
914         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
915         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
916         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
917         const vk::InstanceDriver                        vki                                     (vkp, *instance);
918         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
919         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
920
921         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
922
923         {
924                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
925                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
926                 const vk::DeviceDriver                          vkd                     (vki, *device);
927                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
928
929                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
930                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createSemaphore(vkd, *device));
931                 NativeHandle                                            handle;
932
933                 if (transference == TRANSFERENCE_COPY)
934                         submitDummySignal(vkd, queue, *semaphoreA);
935
936                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
937
938                 submitDummySignal(vkd, queue, *semaphoreB);
939                 submitDummyWait(vkd, queue, *semaphoreB);
940
941                 VK_CHECK(vkd.queueWaitIdle(queue));
942
943                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
944
945                 if (transference == TRANSFERENCE_COPY)
946                         submitDummyWait(vkd, queue, *semaphoreB);
947                 else if (transference == TRANSFERENCE_REFERENCE)
948                 {
949                         submitDummySignal(vkd, queue, *semaphoreA);
950                         submitDummyWait(vkd, queue, *semaphoreB);
951                 }
952                 else
953                         DE_FATAL("Unknown transference.");
954
955                 VK_CHECK(vkd.queueWaitIdle(queue));
956
957                 return tcu::TestStatus::pass("Pass");
958         }
959 }
960
961 tcu::TestStatus testSemaphoreMultipleExports (Context&                                  context,
962                                                                                           const SemaphoreTestConfig     config)
963 {
964         const size_t                                            exportCount                     = 4 * 1024;
965         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
966         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
967         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
968         const vk::InstanceDriver                        vki                                     (vkp, *instance);
969         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
970         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
971
972         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
973
974         {
975                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
976                 const vk::DeviceDriver                          vkd                     (vki, *device);
977                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
978                 const vk::Unique<vk::VkSemaphore>       semaphore       (createExportableSemaphore(vkd, *device, config.externalType));
979
980                 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
981                 {
982                         NativeHandle handle;
983
984                         if (transference == TRANSFERENCE_COPY)
985                                 submitDummySignal(vkd, queue, *semaphore);
986
987                         getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
988                 }
989
990                 submitDummySignal(vkd, queue, *semaphore);
991                 submitDummyWait(vkd, queue, *semaphore);
992
993                 VK_CHECK(vkd.queueWaitIdle(queue));
994         }
995
996         return tcu::TestStatus::pass("Pass");
997 }
998
999 tcu::TestStatus testSemaphoreMultipleImports (Context&                                  context,
1000                                                                                           const SemaphoreTestConfig     config)
1001 {
1002         const size_t                                            importCount                     = 4 * 1024;
1003         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1004         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1005         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1006         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1007         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1008         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1009
1010         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1011
1012         {
1013                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1014                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1015                 const vk::DeviceDriver                          vkd                     (vki, *device);
1016                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1017                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1018                 NativeHandle                                            handleA;
1019
1020                 if (transference == TRANSFERENCE_COPY)
1021                         submitDummySignal(vkd, queue, *semaphoreA);
1022
1023                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1024
1025                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1026                 {
1027                         NativeHandle                                            handleB         (handleA);
1028                         const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1029                 }
1030
1031                 if (transference == TRANSFERENCE_COPY)
1032                 {
1033                         importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1034                         submitDummyWait(vkd, queue, *semaphoreA);
1035                 }
1036                 else if (transference == TRANSFERENCE_REFERENCE)
1037                 {
1038                         submitDummySignal(vkd, queue, *semaphoreA);
1039                         submitDummyWait(vkd, queue, *semaphoreA);
1040                 }
1041                 else
1042                         DE_FATAL("Unknown transference.");
1043
1044                 VK_CHECK(vkd.queueWaitIdle(queue));
1045         }
1046
1047         return tcu::TestStatus::pass("Pass");
1048 }
1049
1050 tcu::TestStatus testSemaphoreTransference (Context&                                             context,
1051                                                                                    const SemaphoreTestConfig    config)
1052 {
1053         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1054         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1055         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1056         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1057         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1058         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1059
1060         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1061
1062         {
1063                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1064                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1065                 const vk::DeviceDriver                          vkd                     (vki, *device);
1066                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1067
1068                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1069                 NativeHandle                                            handle;
1070
1071                 submitDummySignal(vkd, queue, *semaphoreA);
1072
1073                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1074
1075                 {
1076                         const vk::Unique<vk::VkSemaphore>       semaphoreB                      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1077
1078                         if (config.permanence == PERMANENCE_PERMANENT)
1079                         {
1080                                 if (transference == TRANSFERENCE_COPY)
1081                                 {
1082                                         submitDummySignal(vkd, queue, *semaphoreA);
1083                                         submitDummyWait(vkd, queue, *semaphoreB);
1084                                         VK_CHECK(vkd.queueWaitIdle(queue));
1085
1086                                         submitDummySignal(vkd, queue, *semaphoreB);
1087
1088                                         submitDummyWait(vkd, queue, *semaphoreA);
1089                                         submitDummyWait(vkd, queue, *semaphoreB);
1090                                         VK_CHECK(vkd.queueWaitIdle(queue));
1091                                 }
1092                                 else if (transference== TRANSFERENCE_REFERENCE)
1093                                 {
1094                                         submitDummyWait(vkd, queue, *semaphoreB);
1095                                         VK_CHECK(vkd.queueWaitIdle(queue));
1096
1097                                         submitDummySignal(vkd, queue, *semaphoreA);
1098                                         submitDummyWait(vkd, queue, *semaphoreB);
1099
1100                                         submitDummySignal(vkd, queue, *semaphoreB);
1101                                         submitDummyWait(vkd, queue, *semaphoreA);
1102                                         VK_CHECK(vkd.queueWaitIdle(queue));
1103                                 }
1104                                 else
1105                                         DE_FATAL("Unknown transference.");
1106                         }
1107                         else if (config.permanence == PERMANENCE_TEMPORARY)
1108                         {
1109                                 if (transference == TRANSFERENCE_COPY)
1110                                 {
1111                                         submitDummySignal(vkd, queue, *semaphoreA);
1112                                         submitDummyWait(vkd, queue, *semaphoreB);
1113                                         VK_CHECK(vkd.queueWaitIdle(queue));
1114
1115                                         submitDummySignal(vkd, queue, *semaphoreB);
1116
1117                                         submitDummyWait(vkd, queue, *semaphoreA);
1118                                         submitDummyWait(vkd, queue, *semaphoreB);
1119                                         VK_CHECK(vkd.queueWaitIdle(queue));
1120                                 }
1121                                 else if (transference== TRANSFERENCE_REFERENCE)
1122                                 {
1123                                         submitDummyWait(vkd, queue, *semaphoreB);
1124                                         VK_CHECK(vkd.queueWaitIdle(queue));
1125
1126                                         submitDummySignal(vkd, queue, *semaphoreA);
1127                                         submitDummySignal(vkd, queue, *semaphoreB);
1128
1129                                         submitDummyWait(vkd, queue, *semaphoreB);
1130                                         submitDummyWait(vkd, queue, *semaphoreA);
1131                                         VK_CHECK(vkd.queueWaitIdle(queue));
1132                                 }
1133                                 else
1134                                         DE_FATAL("Unknown transference.");
1135                         }
1136                         else
1137                                 DE_FATAL("Unknown permanence.");
1138                 }
1139
1140                 return tcu::TestStatus::pass("Pass");
1141         }
1142 }
1143
1144 tcu::TestStatus testSemaphoreFdDup (Context&                                    context,
1145                                                                         const SemaphoreTestConfig       config)
1146 {
1147 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1148         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1149         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1150         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1151         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1152         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1153         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1154
1155         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1156
1157         {
1158                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1159                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1160                 const vk::DeviceDriver                          vkd                     (vki, *device);
1161                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1162
1163                 TestLog&                                                        log                     = context.getTestContext().getLog();
1164                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1165
1166                 if (transference == TRANSFERENCE_COPY)
1167                         submitDummySignal(vkd, queue, *semaphoreA);
1168
1169                 {
1170                         const NativeHandle      fd              (getSemaphoreFd(vkd, *device, *semaphoreA, config.externalType));
1171                         NativeHandle            newFd   (dup(fd.getFd()));
1172
1173                         if (newFd.getFd() < 0)
1174                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1175
1176                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1177
1178                         {
1179                                 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1180
1181                                 if (transference == TRANSFERENCE_COPY)
1182                                         submitDummyWait(vkd, queue, *semaphoreB);
1183                                 else if (transference == TRANSFERENCE_REFERENCE)
1184                                 {
1185                                         submitDummySignal(vkd, queue, *semaphoreA);
1186                                         submitDummyWait(vkd, queue, *semaphoreB);
1187                                 }
1188                                 else
1189                                         DE_FATAL("Unknown permanence.");
1190                         }
1191                 }
1192
1193                 VK_CHECK(vkd.queueWaitIdle(queue));
1194
1195                 return tcu::TestStatus::pass("Pass");
1196         }
1197 #else
1198         DE_UNREF(context);
1199         DE_UNREF(config);
1200         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1201 #endif
1202 }
1203
1204 tcu::TestStatus testSemaphoreFdDup2 (Context&                                   context,
1205                                                                          const SemaphoreTestConfig      config)
1206 {
1207 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1208         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1209         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1210         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1211         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1212         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1213         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1214
1215         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1216
1217         {
1218                 const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1219                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1220                 const vk::DeviceDriver                          vkd                     (vki, *device);
1221                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1222
1223                 TestLog&                                                        log                     = context.getTestContext().getLog();
1224                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1225                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1226
1227                 if (transference == TRANSFERENCE_COPY)
1228                 {
1229                         submitDummySignal(vkd, queue, *semaphoreA);
1230                         submitDummySignal(vkd, queue, *semaphoreB);
1231                 }
1232
1233                 {
1234                         const NativeHandle      fd                      (getSemaphoreFd(vkd, *device, *semaphoreA, config.externalType));
1235                         NativeHandle            secondFd        (getSemaphoreFd(vkd, *device, *semaphoreB, config.externalType));
1236                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
1237
1238                         if (newFd < 0)
1239                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1240
1241                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1242
1243                         {
1244                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1245
1246                                 if (transference == TRANSFERENCE_COPY)
1247                                         submitDummyWait(vkd, queue, *semaphoreC);
1248                                 else if (transference == TRANSFERENCE_REFERENCE)
1249                                 {
1250                                         submitDummySignal(vkd, queue, *semaphoreA);
1251                                         submitDummyWait(vkd, queue, *semaphoreC);
1252                                 }
1253                                 else
1254                                         DE_FATAL("Unknown permanence.");
1255                         }
1256                 }
1257
1258                 VK_CHECK(vkd.queueWaitIdle(queue));
1259
1260                 return tcu::TestStatus::pass("Pass");
1261         }
1262 #else
1263         DE_UNREF(context);
1264         DE_UNREF(config);
1265         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1266 #endif
1267 }
1268
1269 tcu::TestStatus testSemaphoreFdDup3 (Context&                                   context,
1270                                                                          const SemaphoreTestConfig      config)
1271 {
1272 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1273         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1274         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1275         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1276         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1277         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1278         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1279
1280         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1281
1282         {
1283                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1284                 const vk::DeviceDriver                          vkd                     (vki, *device);
1285                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1286
1287                 TestLog&                                                        log                     = context.getTestContext().getLog();
1288                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1289                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1290
1291                 if (transference == TRANSFERENCE_COPY)
1292                 {
1293                         submitDummySignal(vkd, queue, *semaphoreA);
1294                         submitDummySignal(vkd, queue, *semaphoreB);
1295                 }
1296
1297                 {
1298                         const vk::VkSemaphoreImportFlagsKHR     flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1299                         const NativeHandle                                      fd                      (getSemaphoreFd(vkd, *device, *semaphoreA, config.externalType));
1300                         NativeHandle                                            secondFd        (getSemaphoreFd(vkd, *device, *semaphoreB, config.externalType));
1301                         const int                                                       newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
1302
1303                         if (newFd < 0)
1304                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1305
1306                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1307
1308                         {
1309                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1310
1311                                 if (transference == TRANSFERENCE_COPY)
1312                                         submitDummyWait(vkd, queue, *semaphoreC);
1313                                 else if (transference == TRANSFERENCE_REFERENCE)
1314                                 {
1315                                         submitDummySignal(vkd, queue, *semaphoreA);
1316                                         submitDummyWait(vkd, queue, *semaphoreC);
1317                                 }
1318                                 else
1319                                         DE_FATAL("Unknown permanence.");
1320                         }
1321                 }
1322
1323                 VK_CHECK(vkd.queueWaitIdle(queue));
1324
1325                 return tcu::TestStatus::pass("Pass");
1326         }
1327 #else
1328         DE_UNREF(context);
1329         DE_UNREF(config);
1330         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1331 #endif
1332 }
1333
1334 tcu::TestStatus testSemaphoreFdSendOverSocket (Context&                                         context,
1335                                                                                            const SemaphoreTestConfig    config)
1336 {
1337 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1338         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1339         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1340         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, config.externalType, 0u, 0u));
1341         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1342         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1343         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1344
1345         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1346
1347         {
1348                 const vk::Unique<vk::VkDevice>          device          (createDevice(vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1349                 const vk::DeviceDriver                          vkd                     (vki, *device);
1350                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1351
1352                 TestLog&                                                        log                     = context.getTestContext().getLog();
1353                 const vk::Unique<vk::VkSemaphore>       semaphore       (createExportableSemaphore(vkd, *device, config.externalType));
1354
1355                 if (transference == TRANSFERENCE_COPY)
1356                         submitDummySignal(vkd, queue, *semaphore);
1357
1358                 const NativeHandle      fd      (getSemaphoreFd(vkd, *device, *semaphore, config.externalType));
1359
1360                 {
1361                         int sv[2];
1362
1363                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1364                         {
1365                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1366                                 TCU_FAIL("Failed to create socket pair");
1367                         }
1368
1369                         {
1370                                 const NativeHandle      srcSocket       (sv[0]);
1371                                 const NativeHandle      dstSocket       (sv[1]);
1372                                 std::string                     sendData        ("deqp");
1373
1374                                 // Send FD
1375                                 {
1376                                         const int                       fdRaw   (fd.getFd());
1377                                         msghdr                          msg;
1378                                         cmsghdr*                        cmsg;
1379                                         char                            buffer[CMSG_SPACE(sizeof(int))];
1380                                         iovec                           iov             = { &sendData[0], sendData.length()};
1381
1382                                         deMemset(&msg, 0, sizeof(msg));
1383
1384                                         msg.msg_control         = buffer;
1385                                         msg.msg_controllen      = sizeof(buffer);
1386                                         msg.msg_iovlen          = 1;
1387                                         msg.msg_iov                     = &iov;
1388
1389                                         cmsg                            = CMSG_FIRSTHDR(&msg);
1390                                         cmsg->cmsg_level        = SOL_SOCKET;
1391                                         cmsg->cmsg_type         = SCM_RIGHTS;
1392                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
1393
1394                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1395                                         msg.msg_controllen = cmsg->cmsg_len;
1396
1397                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1398                                         {
1399                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1400                                                 TCU_FAIL("Failed to send fd over socket");
1401                                         }
1402                                 }
1403
1404                                 // Recv FD
1405                                 {
1406                                         msghdr                  msg;
1407                                         char                    buffer[CMSG_SPACE(sizeof(int))];
1408                                         std::string             recvData        (4, '\0');
1409                                         iovec                   iov                     = { &recvData[0], recvData.length() };
1410
1411                                         deMemset(&msg, 0, sizeof(msg));
1412
1413                                         msg.msg_control         = buffer;
1414                                         msg.msg_controllen      = sizeof(buffer);
1415                                         msg.msg_iovlen          = 1;
1416                                         msg.msg_iov                     = &iov;
1417
1418                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1419
1420                                         if (bytes < 0)
1421                                         {
1422                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1423                                                 TCU_FAIL("Failed to recv fd over socket");
1424
1425                                         }
1426                                         else if (bytes != (ssize_t)sendData.length())
1427                                         {
1428                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1429                                         }
1430                                         else
1431                                         {
1432                                                 const vk::VkSemaphoreImportFlagsKHR     flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkSemaphoreImportFlagBitsKHR)0u;
1433                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
1434                                                 int                                                                     newFd_;
1435                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1436                                                 NativeHandle                                            newFd   (newFd_);
1437
1438                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1439                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1440                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1441                                                 TCU_CHECK(recvData == sendData);
1442                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1443
1444                                                 {
1445                                                         const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1446
1447                                                         if (transference == TRANSFERENCE_COPY)
1448                                                                 submitDummyWait(vkd, queue, *newSemaphore);
1449                                                         else if (transference == TRANSFERENCE_REFERENCE)
1450                                                         {
1451                                                                 submitDummySignal(vkd, queue, *newSemaphore);
1452                                                                 submitDummyWait(vkd, queue, *newSemaphore);
1453                                                         }
1454                                                         else
1455                                                                 DE_FATAL("Unknown permanence.");
1456
1457                                                         VK_CHECK(vkd.queueWaitIdle(queue));
1458                                                 }
1459                                         }
1460                                 }
1461                         }
1462                 }
1463         }
1464
1465         return tcu::TestStatus::pass("Pass");
1466 #else
1467         DE_UNREF(context);
1468         DE_UNREF(config);
1469         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1470 #endif
1471 }
1472
1473 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBitsKHR externalType)
1474 {
1475         const vk::PlatformInterface&            vkp                             (context.getPlatformInterface());
1476         const vk::Unique<vk::VkInstance>        instance                (createInstance(vkp, 0u, 0u, externalType));
1477         const vk::InstanceDriver                        vki                             (vkp, *instance);
1478         const vk::VkPhysicalDevice                      device                  (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1479
1480         TestLog&                                                        log                             = context.getTestContext().getLog();
1481
1482         const vk::VkPhysicalDeviceExternalFenceInfoKHR  info                    =
1483         {
1484                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR,
1485                 DE_NULL,
1486                 externalType
1487         };
1488         vk::VkExternalFencePropertiesKHR                                properties      =
1489         {
1490                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR,
1491                 DE_NULL,
1492                 0u,
1493                 0u,
1494                 0u
1495         };
1496
1497         vki.getPhysicalDeviceExternalFencePropertiesKHR(device, &info, &properties);
1498         log << TestLog::Message << properties << TestLog::EndMessage;
1499
1500         TCU_CHECK(properties.pNext == DE_NULL);
1501         TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR);
1502
1503         return tcu::TestStatus::pass("Pass");
1504 }
1505
1506 struct FenceTestConfig
1507 {
1508                                                                                                 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBitsKHR       externalType_,
1509                                                                                                                                  Permanence                                                                     permanence_)
1510                 : externalType          (externalType_)
1511                 , permanence            (permanence_)
1512         {
1513         }
1514
1515         vk::VkExternalFenceHandleTypeFlagBitsKHR        externalType;
1516         Permanence                                                                      permanence;
1517 };
1518
1519
1520 tcu::TestStatus testFenceWin32Create (Context&                          context,
1521                                                                           const FenceTestConfig config)
1522 {
1523 #if (DE_OS == DE_OS_WIN32)
1524         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1525         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1526         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1527         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1528         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1529         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1530
1531         checkFenceSupport(vki, physicalDevice, config.externalType);
1532
1533         {
1534                 const vk::Unique<vk::VkDevice>                          device                  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1535                 const vk::DeviceDriver                                          vkd                             (vki, *device);
1536                 const vk::VkQueue                                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
1537                 const vk::VkExportFenceWin32HandleInfoKHR       win32ExportInfo =
1538                 {
1539                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1540                         DE_NULL,
1541
1542                         (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1543                         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1544                         DE_NULL
1545                 };
1546                 const vk::VkExportFenceCreateInfoKHR            exportCreateInfo=
1547                 {
1548                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR,
1549                         &win32ExportInfo,
1550                         (vk::VkExternalFenceHandleTypeFlagsKHR)config.externalType
1551                 };
1552                 const vk::VkFenceCreateInfo                                     createInfo              =
1553                 {
1554                         vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1555                         &exportCreateInfo,
1556                         0u
1557                 };
1558                 const vk::Unique<vk::VkFence>                           fence           (vk::createFence(vkd, *device, &createInfo));
1559
1560                 if (transference == TRANSFERENCE_COPY)
1561                         submitDummySignal(vkd, queue, *fence);
1562
1563                 NativeHandle                                            handleA;
1564                 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1565
1566                 {
1567                         const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1568                         const vk::Unique<vk::VkFence>   fenceA  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1569
1570                         if (transference == TRANSFERENCE_COPY)
1571                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1572                         else if (transference == TRANSFERENCE_REFERENCE)
1573                         {
1574                                 submitDummySignal(vkd, queue, *fence);
1575                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1576                         }
1577                         else
1578                                 DE_FATAL("Unknown transference.");
1579
1580                         VK_CHECK(vkd.queueWaitIdle(queue));
1581                 }
1582
1583                 return tcu::TestStatus::pass("Pass");
1584         }
1585 #else
1586         DE_UNREF(context);
1587         DE_UNREF(config);
1588         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1589 #endif
1590 }
1591
1592 tcu::TestStatus testFenceImportTwice (Context&                          context,
1593                                                                           const FenceTestConfig config)
1594 {
1595         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1596         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1597         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1598         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1599         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1600         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1601
1602         checkFenceSupport(vki, physicalDevice, config.externalType);
1603
1604         {
1605                 const vk::Unique<vk::VkDevice>  device          (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1606                 const vk::DeviceDriver                  vkd                     (vki, *device);
1607                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
1608                 const vk::Unique<vk::VkFence>   fence           (createExportableFence(vkd, *device, config.externalType));
1609
1610                 if (transference == TRANSFERENCE_COPY)
1611                         submitDummySignal(vkd, queue, *fence);
1612
1613                 NativeHandle                                            handleA;
1614                 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1615
1616                 {
1617                         NativeHandle                                    handleB (handleA);
1618                         const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1619                         const vk::Unique<vk::VkFence>   fenceA  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1620                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1621
1622                         if (transference == TRANSFERENCE_COPY)
1623                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1624                         else if (transference == TRANSFERENCE_REFERENCE)
1625                         {
1626                                 submitDummySignal(vkd, queue, *fenceA);
1627                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1628                         }
1629                         else
1630                                 DE_FATAL("Unknown transference.");
1631
1632                         VK_CHECK(vkd.queueWaitIdle(queue));
1633                 }
1634
1635                 return tcu::TestStatus::pass("Pass");
1636         }
1637 }
1638
1639 tcu::TestStatus testFenceImportReimport (Context&                               context,
1640                                                                                  const FenceTestConfig  config)
1641 {
1642         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1643         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1644         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1645         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1646         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1647         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1648
1649         checkFenceSupport(vki, physicalDevice, config.externalType);
1650
1651         {
1652                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1653                 const vk::DeviceDriver                  vkd             (vki, *device);
1654                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1655
1656                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1657
1658                 if (transference == TRANSFERENCE_COPY)
1659                         submitDummySignal(vkd, queue, *fenceA);
1660
1661                 NativeHandle                                    handleA;
1662                 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1663
1664                 NativeHandle                                    handleB (handleA);
1665                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1666                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1667
1668                 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1669
1670                 if (transference == TRANSFERENCE_COPY)
1671                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1672                 else if (transference == TRANSFERENCE_REFERENCE)
1673                 {
1674                         submitDummySignal(vkd, queue, *fenceA);
1675                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1676                 }
1677                 else
1678                         DE_FATAL("Unknown transference.");
1679
1680                 VK_CHECK(vkd.queueWaitIdle(queue));
1681
1682                 return tcu::TestStatus::pass("Pass");
1683         }
1684 }
1685
1686 tcu::TestStatus testFenceSignalExportImportWait (Context&                               context,
1687                                                                                                  const FenceTestConfig  config)
1688 {
1689         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1690         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1691         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1692         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1693         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1694
1695         checkFenceSupport(vki, physicalDevice, config.externalType);
1696
1697         {
1698                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1699                 const vk::DeviceDriver                  vkd             (vki, *device);
1700                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1701                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1702
1703                 submitDummySignal(vkd, queue, *fenceA);
1704
1705                 {
1706                         NativeHandle    handle;
1707
1708                         getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1709
1710                         {
1711                                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1712                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1713                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1714
1715                                 VK_CHECK(vkd.queueWaitIdle(queue));
1716                         }
1717                 }
1718
1719                 return tcu::TestStatus::pass("Pass");
1720         }
1721 }
1722
1723 tcu::TestStatus testFenceExportSignalImportWait (Context&                               context,
1724                                                                                                  const FenceTestConfig  config)
1725 {
1726         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1727         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1728         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1729         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1730         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1731         const vk::VkFenceImportFlagsKHR         flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1732
1733         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1734         checkFenceSupport(vki, physicalDevice, config.externalType);
1735
1736         {
1737                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1738                 const vk::DeviceDriver                  vkd             (vki, *device);
1739                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1740
1741                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1742                 NativeHandle                                    handle;
1743
1744                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1745
1746                 submitDummySignal(vkd, queue, *fenceA);
1747                 {
1748                         {
1749                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1750
1751                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1752                                 VK_CHECK(vkd.queueWaitIdle(queue));
1753                         }
1754                 }
1755
1756                 return tcu::TestStatus::pass("Pass");
1757         }
1758 }
1759
1760 tcu::TestStatus testFenceExportImportSignalWait (Context&                               context,
1761                                                                                                  const FenceTestConfig  config)
1762 {
1763         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1764         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1765         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1766         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1767         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1768
1769         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1770         checkFenceSupport(vki, physicalDevice, config.externalType);
1771
1772         {
1773                 const vk::VkFenceImportFlagsKHR flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1774                 const vk::Unique<vk::VkDevice>  device          (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1775                 const vk::DeviceDriver                  vkd                     (vki, *device);
1776                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
1777
1778                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1779                 NativeHandle                                    handle;
1780
1781                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1782
1783                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1784
1785                 submitDummySignal(vkd, queue, *fenceA);
1786                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1787
1788                 VK_CHECK(vkd.queueWaitIdle(queue));
1789
1790                 return tcu::TestStatus::pass("Pass");
1791         }
1792 }
1793
1794 tcu::TestStatus testFenceSignalImport (Context&                                 context,
1795                                                                            const FenceTestConfig        config)
1796 {
1797         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1798         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1799         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1800         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1801         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1802         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1803
1804         checkFenceSupport(vki, physicalDevice, config.externalType);
1805
1806         {
1807                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1808                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1809                 const vk::DeviceDriver                  vkd             (vki, *device);
1810                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1811
1812                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1813                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
1814                 NativeHandle                                    handle;
1815
1816                 submitDummySignal(vkd, queue, *fenceB);
1817                 VK_CHECK(vkd.queueWaitIdle(queue));
1818
1819                 if (transference == TRANSFERENCE_COPY)
1820                         submitDummySignal(vkd, queue, *fenceA);
1821
1822                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1823
1824                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
1825
1826                 if (transference == TRANSFERENCE_COPY)
1827                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1828                 else if (transference == TRANSFERENCE_REFERENCE)
1829                 {
1830                         submitDummySignal(vkd, queue, *fenceA);
1831                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1832                 }
1833                 else
1834                         DE_FATAL("Unknown transference.");
1835
1836                 VK_CHECK(vkd.queueWaitIdle(queue));
1837
1838                 return tcu::TestStatus::pass("Pass");
1839         }
1840 }
1841
1842 tcu::TestStatus testFenceReset (Context&                                context,
1843                                                                 const FenceTestConfig   config)
1844 {
1845         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1846         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1847         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1848         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1849         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1850         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1851
1852         checkFenceSupport(vki, physicalDevice, config.externalType);
1853
1854         {
1855                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1856                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1857                 const vk::DeviceDriver                  vkd             (vki, *device);
1858                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1859
1860                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1861                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
1862                 const vk::Unique<vk::VkFence>   fenceC  (createFence(vkd, *device));
1863                 NativeHandle                                    handle;
1864
1865                 submitDummySignal(vkd, queue, *fenceB);
1866                 VK_CHECK(vkd.queueWaitIdle(queue));
1867
1868                 submitDummySignal(vkd, queue, *fenceA);
1869
1870                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1871                 {
1872                         NativeHandle                                    handleB (handle);
1873                         importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1874                 }
1875                 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
1876
1877                 VK_CHECK(vkd.queueWaitIdle(queue));
1878                 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
1879
1880                 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
1881                 {
1882                         // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
1883                         // or fenceB should be separate copy of the payload and not affect fenceC
1884                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
1885
1886                         // vkResetFences() should have restored fenceBs prior state and should be now reset
1887                         // or fenceB should have it's separate payload
1888                         submitDummySignal(vkd, queue, *fenceB);
1889                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1890                 }
1891                 else if (config.permanence == PERMANENCE_PERMANENT)
1892                 {
1893                         DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
1894
1895                         // Reset fences should have reset all of the fences
1896                         submitDummySignal(vkd, queue, *fenceC);
1897
1898                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1899                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1900                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
1901                 }
1902                 else
1903                         DE_FATAL("Unknown permanence");
1904
1905                 VK_CHECK(vkd.queueWaitIdle(queue));
1906
1907                 return tcu::TestStatus::pass("Pass");
1908         }
1909 }
1910
1911 tcu::TestStatus testFenceSignalWaitImport (Context&                                     context,
1912                                                                                    const FenceTestConfig        config)
1913 {
1914         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1915         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1916         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1917         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1918         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1919         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1920
1921         checkFenceSupport(vki, physicalDevice, config.externalType);
1922
1923         {
1924                 const vk::VkFenceImportFlagsKHR flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
1925                 const vk::Unique<vk::VkDevice>  device          (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1926                 const vk::DeviceDriver                  vkd                     (vki, *device);
1927                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
1928
1929                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
1930                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
1931                 NativeHandle                                    handle;
1932
1933                 if (transference == TRANSFERENCE_COPY)
1934                         submitDummySignal(vkd, queue, *fenceA);
1935
1936                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1937
1938                 submitDummySignal(vkd, queue, *fenceB);
1939                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1940
1941                 VK_CHECK(vkd.queueWaitIdle(queue));
1942
1943                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
1944
1945                 if (transference == TRANSFERENCE_COPY)
1946                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1947                 else if (transference == TRANSFERENCE_REFERENCE)
1948                 {
1949                         submitDummySignal(vkd, queue, *fenceA);
1950                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1951                 }
1952                 else
1953                         DE_FATAL("Unknown transference.");
1954
1955                 VK_CHECK(vkd.queueWaitIdle(queue));
1956
1957                 return tcu::TestStatus::pass("Pass");
1958         }
1959 }
1960
1961 tcu::TestStatus testFenceMultipleExports (Context&                              context,
1962                                                                                   const FenceTestConfig config)
1963 {
1964         const size_t                                            exportCount                     = 4 * 1024;
1965         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1966         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1967         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
1968         const vk::InstanceDriver                        vki                                     (vkp, *instance);
1969         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1970         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1971
1972         checkFenceSupport(vki, physicalDevice, config.externalType);
1973
1974         {
1975                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1976                 const vk::DeviceDriver                  vkd             (vki, *device);
1977                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
1978                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
1979
1980                 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1981                 {
1982                         NativeHandle handle;
1983
1984                         if (transference == TRANSFERENCE_COPY)
1985                                 submitDummySignal(vkd, queue, *fence);
1986
1987                         getFenceNative(vkd, *device, *fence, config.externalType, handle);
1988                 }
1989
1990                 submitDummySignal(vkd, queue, *fence);
1991                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
1992
1993                 VK_CHECK(vkd.queueWaitIdle(queue));
1994         }
1995
1996         return tcu::TestStatus::pass("Pass");
1997 }
1998
1999 tcu::TestStatus testFenceMultipleImports (Context&                              context,
2000                                                                                   const FenceTestConfig config)
2001 {
2002         const size_t                                            importCount                     = 4 * 1024;
2003         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2004         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2005         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2006         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2007         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2008         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2009
2010         checkFenceSupport(vki, physicalDevice, config.externalType);
2011
2012         {
2013                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2014                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2015                 const vk::DeviceDriver                  vkd             (vki, *device);
2016                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2017                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2018                 NativeHandle                                    handleA;
2019
2020                 if (transference == TRANSFERENCE_COPY)
2021                         submitDummySignal(vkd, queue, *fenceA);
2022
2023                 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2024
2025                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2026                 {
2027                         NativeHandle                                    handleB         (handleA);
2028                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2029                 }
2030
2031                 if (transference == TRANSFERENCE_COPY)
2032                 {
2033                         importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2034                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2035                 }
2036                 else if (transference == TRANSFERENCE_REFERENCE)
2037                 {
2038                         submitDummySignal(vkd, queue, *fenceA);
2039                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2040                 }
2041                 else
2042                         DE_FATAL("Unknown transference.");
2043
2044                 VK_CHECK(vkd.queueWaitIdle(queue));
2045         }
2046
2047         return tcu::TestStatus::pass("Pass");
2048 }
2049
2050 tcu::TestStatus testFenceTransference (Context&                                 context,
2051                                                                            const FenceTestConfig        config)
2052 {
2053         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2054         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2055         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2056         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2057         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2058         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2059
2060         checkFenceSupport(vki, physicalDevice, config.externalType);
2061
2062         {
2063                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2064                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2065                 const vk::DeviceDriver                  vkd             (vki, *device);
2066                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2067
2068                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2069                 NativeHandle                                    handle;
2070
2071                 submitDummySignal(vkd, queue, *fenceA);
2072
2073                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2074
2075                 {
2076                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2077
2078                         if (config.permanence == PERMANENCE_PERMANENT)
2079                         {
2080                                 if (transference == TRANSFERENCE_COPY)
2081                                 {
2082                                         submitDummySignal(vkd, queue, *fenceA);
2083                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2084                                         VK_CHECK(vkd.queueWaitIdle(queue));
2085
2086                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2087                                         submitDummySignal(vkd, queue, *fenceB);
2088
2089                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2090                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2091                                         VK_CHECK(vkd.queueWaitIdle(queue));
2092                                 }
2093                                 else if (transference== TRANSFERENCE_REFERENCE)
2094                                 {
2095                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2096                                         VK_CHECK(vkd.queueWaitIdle(queue));
2097
2098                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2099                                         submitDummySignal(vkd, queue, *fenceA);
2100                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2101
2102                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2103                                         submitDummySignal(vkd, queue, *fenceB);
2104                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2105                                         VK_CHECK(vkd.queueWaitIdle(queue));
2106                                 }
2107                                 else
2108                                         DE_FATAL("Unknown transference.");
2109                         }
2110                         else if (config.permanence == PERMANENCE_TEMPORARY)
2111                         {
2112                                 if (transference == TRANSFERENCE_COPY)
2113                                 {
2114                                         submitDummySignal(vkd, queue, *fenceA);
2115                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2116                                         VK_CHECK(vkd.queueWaitIdle(queue));
2117
2118                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2119                                         submitDummySignal(vkd, queue, *fenceB);
2120
2121                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2122                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2123                                         VK_CHECK(vkd.queueWaitIdle(queue));
2124                                 }
2125                                 else if (transference == TRANSFERENCE_REFERENCE)
2126                                 {
2127                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2128                                         VK_CHECK(vkd.queueWaitIdle(queue));
2129
2130                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2131                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2132                                         submitDummySignal(vkd, queue, *fenceA);
2133                                         submitDummySignal(vkd, queue, *fenceB);
2134
2135                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2136                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2137                                         VK_CHECK(vkd.queueWaitIdle(queue));
2138                                 }
2139                                 else
2140                                         DE_FATAL("Unknown transference.");
2141                         }
2142                         else
2143                                 DE_FATAL("Unknown permanence.");
2144                 }
2145
2146                 return tcu::TestStatus::pass("Pass");
2147         }
2148 }
2149
2150 tcu::TestStatus testFenceFdDup (Context&                                context,
2151                                                                 const FenceTestConfig   config)
2152 {
2153 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2154         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2155         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2156         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2157         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2158         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2159         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2160
2161         checkFenceSupport(vki, physicalDevice, config.externalType);
2162
2163         {
2164                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2165                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2166                 const vk::DeviceDriver                  vkd             (vki, *device);
2167                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2168
2169                 TestLog&                                                log             = context.getTestContext().getLog();
2170                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2171
2172                 if (transference == TRANSFERENCE_COPY)
2173                         submitDummySignal(vkd, queue, *fenceA);
2174
2175                 {
2176                         const NativeHandle      fd              (getFenceFd(vkd, *device, *fenceA, config.externalType));
2177                         NativeHandle            newFd   (dup(fd.getFd()));
2178
2179                         if (newFd.getFd() < 0)
2180                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2181
2182                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2183
2184                         {
2185                                 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2186
2187                                 if (transference == TRANSFERENCE_COPY)
2188                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2189                                 else if (transference == TRANSFERENCE_REFERENCE)
2190                                 {
2191                                         submitDummySignal(vkd, queue, *fenceA);
2192                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2193                                 }
2194                                 else
2195                                         DE_FATAL("Unknown permanence.");
2196                         }
2197                 }
2198
2199                 VK_CHECK(vkd.queueWaitIdle(queue));
2200
2201                 return tcu::TestStatus::pass("Pass");
2202         }
2203 #else
2204         DE_UNREF(context);
2205         DE_UNREF(config);
2206         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2207 #endif
2208 }
2209
2210 tcu::TestStatus testFenceFdDup2 (Context&                               context,
2211                                                                  const FenceTestConfig  config)
2212 {
2213 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2214         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2215         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2216         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2217         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2218         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2219         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2220
2221         checkFenceSupport(vki, physicalDevice, config.externalType);
2222
2223         {
2224                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2225                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2226                 const vk::DeviceDriver                  vkd             (vki, *device);
2227                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2228
2229                 TestLog&                                                log             = context.getTestContext().getLog();
2230                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2231                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2232
2233                 if (transference == TRANSFERENCE_COPY)
2234                 {
2235                         submitDummySignal(vkd, queue, *fenceA);
2236                         submitDummySignal(vkd, queue, *fenceB);
2237                 }
2238
2239                 {
2240                         const NativeHandle      fd                      (getFenceFd(vkd, *device, *fenceA, config.externalType));
2241                         NativeHandle            secondFd        (getFenceFd(vkd, *device, *fenceB, config.externalType));
2242                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
2243
2244                         if (newFd < 0)
2245                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2246
2247                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2248
2249                         {
2250                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2251
2252                                 if (transference == TRANSFERENCE_COPY)
2253                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2254                                 else if (transference == TRANSFERENCE_REFERENCE)
2255                                 {
2256                                         submitDummySignal(vkd, queue, *fenceA);
2257                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2258                                 }
2259                                 else
2260                                         DE_FATAL("Unknown permanence.");
2261                         }
2262                 }
2263
2264                 VK_CHECK(vkd.queueWaitIdle(queue));
2265
2266                 return tcu::TestStatus::pass("Pass");
2267         }
2268 #else
2269         DE_UNREF(context);
2270         DE_UNREF(config);
2271         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2272 #endif
2273 }
2274
2275 tcu::TestStatus testFenceFdDup3 (Context&                               context,
2276                                                                  const FenceTestConfig  config)
2277 {
2278 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2279         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2280         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2281         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2282         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2283         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2284         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2285
2286         checkFenceSupport(vki, physicalDevice, config.externalType);
2287
2288         {
2289                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2290                 const vk::DeviceDriver                  vkd             (vki, *device);
2291                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2292
2293                 TestLog&                                                log             = context.getTestContext().getLog();
2294                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2295                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2296
2297                 if (transference == TRANSFERENCE_COPY)
2298                 {
2299                         submitDummySignal(vkd, queue, *fenceA);
2300                         submitDummySignal(vkd, queue, *fenceB);
2301                 }
2302
2303                 {
2304                         const vk::VkFenceImportFlagsKHR flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2305                         const NativeHandle                              fd                      (getFenceFd(vkd, *device, *fenceA, config.externalType));
2306                         NativeHandle                                    secondFd        (getFenceFd(vkd, *device, *fenceB, config.externalType));
2307                         const int                                               newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
2308
2309                         if (newFd < 0)
2310                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2311
2312                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2313
2314                         {
2315                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2316
2317                                 if (transference == TRANSFERENCE_COPY)
2318                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2319                                 else if (transference == TRANSFERENCE_REFERENCE)
2320                                 {
2321                                         submitDummySignal(vkd, queue, *fenceA);
2322                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2323                                 }
2324                                 else
2325                                         DE_FATAL("Unknown permanence.");
2326                         }
2327                 }
2328
2329                 VK_CHECK(vkd.queueWaitIdle(queue));
2330
2331                 return tcu::TestStatus::pass("Pass");
2332         }
2333 #else
2334         DE_UNREF(context);
2335         DE_UNREF(config);
2336         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2337 #endif
2338 }
2339
2340 tcu::TestStatus testFenceFdSendOverSocket (Context&                                     context,
2341                                                                                    const FenceTestConfig        config)
2342 {
2343 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2344         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2345         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2346         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, 0u, config.externalType));
2347         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2348         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2349         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2350
2351         checkFenceSupport(vki, physicalDevice, config.externalType);
2352
2353         {
2354                 const vk::Unique<vk::VkDevice>  device  (createDevice(vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2355                 const vk::DeviceDriver                  vkd             (vki, *device);
2356                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2357
2358                 TestLog&                                                log             = context.getTestContext().getLog();
2359                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
2360
2361                 if (transference == TRANSFERENCE_COPY)
2362                         submitDummySignal(vkd, queue, *fence);
2363
2364                 const NativeHandle      fd      (getFenceFd(vkd, *device, *fence, config.externalType));
2365
2366                 {
2367                         int sv[2];
2368
2369                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2370                         {
2371                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2372                                 TCU_FAIL("Failed to create socket pair");
2373                         }
2374
2375                         {
2376                                 const NativeHandle      srcSocket       (sv[0]);
2377                                 const NativeHandle      dstSocket       (sv[1]);
2378                                 std::string                     sendData        ("deqp");
2379
2380                                 // Send FD
2381                                 {
2382                                         const int                       fdRaw   (fd.getFd());
2383                                         msghdr                          msg;
2384                                         cmsghdr*                        cmsg;
2385                                         char                            buffer[CMSG_SPACE(sizeof(int))];
2386                                         iovec                           iov             = { &sendData[0], sendData.length()};
2387
2388                                         deMemset(&msg, 0, sizeof(msg));
2389
2390                                         msg.msg_control         = buffer;
2391                                         msg.msg_controllen      = sizeof(buffer);
2392                                         msg.msg_iovlen          = 1;
2393                                         msg.msg_iov                     = &iov;
2394
2395                                         cmsg                            = CMSG_FIRSTHDR(&msg);
2396                                         cmsg->cmsg_level        = SOL_SOCKET;
2397                                         cmsg->cmsg_type         = SCM_RIGHTS;
2398                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
2399
2400                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2401                                         msg.msg_controllen = cmsg->cmsg_len;
2402
2403                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2404                                         {
2405                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2406                                                 TCU_FAIL("Failed to send fd over socket");
2407                                         }
2408                                 }
2409
2410                                 // Recv FD
2411                                 {
2412                                         msghdr                  msg;
2413                                         char                    buffer[CMSG_SPACE(sizeof(int))];
2414                                         std::string             recvData        (4, '\0');
2415                                         iovec                   iov                     = { &recvData[0], recvData.length() };
2416
2417                                         deMemset(&msg, 0, sizeof(msg));
2418
2419                                         msg.msg_control         = buffer;
2420                                         msg.msg_controllen      = sizeof(buffer);
2421                                         msg.msg_iovlen          = 1;
2422                                         msg.msg_iov                     = &iov;
2423
2424                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2425
2426                                         if (bytes < 0)
2427                                         {
2428                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2429                                                 TCU_FAIL("Failed to recv fd over socket");
2430
2431                                         }
2432                                         else if (bytes != (ssize_t)sendData.length())
2433                                         {
2434                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2435                                         }
2436                                         else
2437                                         {
2438                                                 const vk::VkFenceImportFlagsKHR flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT_KHR : (vk::VkFenceImportFlagBitsKHR)0u;
2439                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
2440                                                 int                                                                     newFd_;
2441                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2442                                                 NativeHandle                                            newFd   (newFd_);
2443
2444                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2445                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2446                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2447                                                 TCU_CHECK(recvData == sendData);
2448                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2449
2450                                                 {
2451                                                         const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2452
2453                                                         if (transference == TRANSFERENCE_COPY)
2454                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2455                                                         else if (transference == TRANSFERENCE_REFERENCE)
2456                                                         {
2457                                                                 submitDummySignal(vkd, queue, *newFence);
2458                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2459                                                         }
2460                                                         else
2461                                                                 DE_FATAL("Unknown permanence.");
2462
2463                                                         VK_CHECK(vkd.queueWaitIdle(queue));
2464                                                 }
2465                                         }
2466                                 }
2467                         }
2468                 }
2469         }
2470
2471         return tcu::TestStatus::pass("Pass");
2472 #else
2473         DE_UNREF(context);
2474         DE_UNREF(config);
2475         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2476 #endif
2477 }
2478
2479 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
2480 {
2481         const vk::VkBufferCreateFlags           createFlags[]           =
2482         {
2483                 0u,
2484                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2485                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2486                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2487         };
2488         const vk::VkBufferUsageFlags            usageFlags[]            =
2489         {
2490                 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2491                 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2492                 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2493                 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2494                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2495                 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2496                 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2497                 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2498                 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2499         };
2500         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2501         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, externalType, 0u));
2502         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2503         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2504         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2505         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2506
2507         // VkDevice is only created if physical device claims to support any of these types.
2508         vk::Move<vk::VkDevice>                          device;
2509         de::MovePtr<vk::DeviceDriver>           vkd;
2510         bool                                                            deviceHasDedicated      = false;
2511
2512         TestLog&                                                        log                                     = context.getTestContext().getLog();
2513
2514         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2515         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2516         {
2517                 const vk::VkBufferViewCreateFlags                               createFlag              = createFlags[createFlagNdx];
2518                 const vk::VkBufferUsageFlags                                    usageFlag               = usageFlags[usageFlagNdx];
2519                 const vk::VkPhysicalDeviceExternalBufferInfoKHR info                    =
2520                 {
2521                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
2522                         DE_NULL,
2523                         createFlag,
2524                         usageFlag,
2525                         externalType
2526                 };
2527                 vk::VkExternalBufferPropertiesKHR                               properties              =
2528                 {
2529                         vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
2530                         DE_NULL,
2531                         { 0u, 0u, 0u }
2532                 };
2533
2534                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2535                         (deviceFeatures.sparseBinding == VK_FALSE))
2536                         continue;
2537
2538                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2539                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2540                         continue;
2541
2542                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2543                         (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2544                         continue;
2545
2546                 vki.getPhysicalDeviceExternalBufferPropertiesKHR(physicalDevice, &info, &properties);
2547
2548                 log << TestLog::Message << properties << TestLog::EndMessage;
2549
2550                 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR);
2551                 TCU_CHECK(properties.pNext == DE_NULL);
2552                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2553
2554                 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)) != 0)
2555                 {
2556                         const bool      requiresDedicated       = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
2557
2558                         if (!device || (requiresDedicated && !deviceHasDedicated))
2559                         {
2560                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2561                                 try
2562                                 {
2563                                         device                          = createDevice(vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2564                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
2565                                         deviceHasDedicated      = requiresDedicated;
2566                                 }
2567                                 catch (const tcu::NotSupportedError& e)
2568                                 {
2569                                         log << e;
2570                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2571                                 }
2572                         }
2573                 }
2574
2575                 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) != 0)
2576                 {
2577                         DE_ASSERT(!!device);
2578                         DE_ASSERT(vkd);
2579
2580                         if (deviceHasDedicated)
2581                         {
2582                                 const vk::Unique<vk::VkBuffer>                          buffer                                          (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2583                                 const vk::VkMemoryDedicatedRequirementsKHR      reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2584                                 const bool                                                                      propertiesRequiresDedicated     = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
2585                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
2586
2587                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
2588                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2589                         }
2590                         else
2591                         {
2592                                 // We can't query whether dedicated memory is required or not on per-object basis.
2593                                 // This check should be redundant as the code above tries to create device with
2594                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2595                                 // is required. However, checking again doesn't hurt.
2596                                 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) == 0);
2597                         }
2598                 }
2599         }
2600
2601         return tcu::TestStatus::pass("Pass");
2602 }
2603
2604 struct MemoryTestConfig
2605 {
2606                                                                                                 MemoryTestConfig        (vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType_,
2607                                                                                                                                          bool                                                                           hostVisible_,
2608                                                                                                                                          bool                                                                           dedicated_)
2609                 : externalType  (externalType_)
2610                 , hostVisible   (hostVisible_)
2611                 , dedicated             (dedicated_)
2612         {
2613         }
2614
2615         vk::VkExternalMemoryHandleTypeFlagBitsKHR       externalType;
2616         bool                                                                            hostVisible;
2617         bool                                                                            dedicated;
2618 };
2619
2620 #if (DE_OS == DE_OS_WIN32)
2621 deUint32 chooseMemoryType (deUint32 bits)
2622 {
2623         if (bits == 0)
2624                 TCU_THROW(NotSupportedError, "No compatible memory type found");
2625
2626         return deCtz32(bits);
2627 }
2628 #endif
2629
2630 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2631 {
2632 #if (DE_OS == DE_OS_WIN32)
2633         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
2634         const vk::Unique<vk::VkInstance>                        instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2635         const vk::InstanceDriver                                        vki                                     (vkp, *instance);
2636         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2637         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2638         const vk::Unique<vk::VkDevice>                          device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2639         const vk::DeviceDriver                                          vkd                                     (vki, *device);
2640         const vk::VkBufferUsageFlags                            usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2641         const deUint32                                                          seed                            = 1261033864u;
2642         const vk::VkDeviceSize                                          bufferSize                      = 1024;
2643         const std::vector<deUint8>                                      testData                        (genTestData(seed, (size_t)bufferSize));
2644
2645         const vk::VkPhysicalDeviceMemoryProperties      memoryProps                     = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2646         const deUint32                                                          compatibleMemTypes      = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2647
2648         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2649
2650         // \note Buffer is only allocated to get memory requirements
2651         deUint32                                                                        exportedMemoryTypeIndex = ~0U;
2652         const vk::Unique<vk::VkBuffer>                          buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2653         const vk::VkMemoryRequirements                          requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2654         const vk::VkExportMemoryWin32HandleInfoKHR      win32Info                               =
2655         {
2656                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2657                 DE_NULL,
2658
2659                 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2660                 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2661                 DE_NULL
2662         };
2663         const vk::VkExportMemoryAllocateInfoKHR         exportInfo                      =
2664         {
2665                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
2666                 &win32Info,
2667                 (vk::VkExternalMemoryHandleTypeFlagsKHR)config.externalType
2668         };
2669
2670         exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2671         const vk::VkMemoryAllocateInfo                          info                            =
2672         {
2673                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2674                 &exportInfo,
2675                 requirements.size,
2676                 exportedMemoryTypeIndex
2677         };
2678         const vk::Unique<vk::VkDeviceMemory>            memory                          (vk::allocateMemory(vkd, *device, &info));
2679         NativeHandle                                                            handleA;
2680
2681         if (config.hostVisible)
2682                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2683
2684         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2685
2686         {
2687                 const vk::Unique<vk::VkDeviceMemory>    memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2688
2689                 if (config.hostVisible)
2690                 {
2691                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2692                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2693
2694                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2695                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testData[0]);
2696
2697                         writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2698                         writeHostMemory(vkd, *device, *memory,  testDataA.size(), &testDataB[0]);
2699
2700                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2701                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testDataB[0]);
2702                 }
2703         }
2704
2705         return tcu::TestStatus::pass("Pass");
2706 #else
2707         DE_UNREF(context);
2708         DE_UNREF(config);
2709         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2710 #endif
2711 }
2712
2713 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2714 {
2715         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
2716         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2717         const vk::InstanceDriver                                vki                                     (vkp, *instance);
2718         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2719         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2720         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2721         const vk::DeviceDriver                                  vkd                                     (vki, *device);
2722         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2723         const deUint32                                                  seed                            = 1261033864u;
2724         const vk::VkDeviceSize                                  bufferSize                      = 1024;
2725         const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
2726
2727         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2728
2729         deUint32                                                                exportedMemoryTypeIndex = ~0U;
2730         // \note Buffer is only allocated to get memory requirements
2731         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2732         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2733         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2734         NativeHandle                                                    handleA;
2735
2736         if (config.hostVisible)
2737                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2738
2739         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2740
2741         {
2742                 NativeHandle                                                    handleB (handleA);
2743                 const vk::Unique<vk::VkDeviceMemory>    memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2744                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2745
2746                 if (config.hostVisible)
2747                 {
2748                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2749                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2750
2751                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2752                         checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
2753
2754                         writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
2755                         writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
2756
2757                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2758                         checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2759                 }
2760         }
2761
2762         return tcu::TestStatus::pass("Pass");
2763 }
2764
2765 tcu::TestStatus testMemoryMultimpleImports (Context& context, MemoryTestConfig config)
2766 {
2767         const size_t                                                    count                           = 4 * 1024;
2768         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
2769         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2770         const vk::InstanceDriver                                vki                                     (vkp, *instance);
2771         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2772         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2773         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2774         const vk::DeviceDriver                                  vkd                                     (vki, *device);
2775         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2776         const vk::VkDeviceSize                                  bufferSize                      = 1024;
2777
2778         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2779
2780         deUint32                                                                exportedMemoryTypeIndex = ~0U;
2781         // \note Buffer is only allocated to get memory requirements
2782         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2783         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2784         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2785         NativeHandle                                                    handleA;
2786
2787         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2788
2789         for (size_t ndx = 0; ndx < count; ndx++)
2790         {
2791                 NativeHandle                                                    handleB (handleA);
2792                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2793         }
2794
2795         return tcu::TestStatus::pass("Pass");
2796 }
2797
2798 tcu::TestStatus testMemoryMultimpleExports (Context& context, MemoryTestConfig config)
2799 {
2800         const size_t                                                    count                           = 4 * 1024;
2801         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
2802         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2803         const vk::InstanceDriver                                vki                                     (vkp, *instance);
2804         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2805         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2806         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2807         const vk::DeviceDriver                                  vkd                                     (vki, *device);
2808         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2809         const vk::VkDeviceSize                                  bufferSize                      = 1024;
2810
2811         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2812
2813         deUint32                                                                exportedMemoryTypeIndex = ~0U;
2814         // \note Buffer is only allocated to get memory requirements
2815         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2816         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2817         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2818
2819         for (size_t ndx = 0; ndx < count; ndx++)
2820         {
2821                 NativeHandle    handle;
2822                 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
2823         }
2824
2825         return tcu::TestStatus::pass("Pass");
2826 }
2827
2828 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
2829 {
2830 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2831         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2832         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2833         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2834         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2835         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2836
2837         {
2838                 const vk::Unique<vk::VkDevice>                  device                  (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2839                 const vk::DeviceDriver                                  vkd                             (vki, *device);
2840
2841                 TestLog&                                                                log                             = context.getTestContext().getLog();
2842                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2843                 const vk::VkDeviceSize                                  bufferSize              = 1024;
2844                 const deUint32                                                  seed                    = 851493858u;
2845                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
2846
2847                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2848
2849                 deUint32                                                                exportedMemoryTypeIndex = ~0U;
2850                 // \note Buffer is only allocated to get memory requirements
2851                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2852                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2853                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2854
2855                 if (config.hostVisible)
2856                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2857
2858                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
2859                 NativeHandle                                                    newFd                   (dup(fd.getFd()));
2860
2861                 if (newFd.getFd() < 0)
2862                         log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2863
2864                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
2865
2866                 {
2867                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
2868
2869                         if (config.hostVisible)
2870                         {
2871                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 672929437u, (size_t)bufferSize));
2872
2873                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
2874
2875                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
2876                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
2877                         }
2878                 }
2879
2880                 return tcu::TestStatus::pass("Pass");
2881         }
2882 #else
2883         DE_UNREF(context);
2884         DE_UNREF(config);
2885         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2886 #endif
2887 }
2888
2889 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
2890 {
2891 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2892         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2893         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2894         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2895         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2896         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2897
2898         {
2899                 const vk::Unique<vk::VkDevice>                  device                  (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2900                 const vk::DeviceDriver                                  vkd                             (vki, *device);
2901
2902                 TestLog&                                                                log                             = context.getTestContext().getLog();
2903                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2904                 const vk::VkDeviceSize                                  bufferSize              = 1024;
2905                 const deUint32                                                  seed                    = 224466865u;
2906                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
2907
2908                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2909
2910                 deUint32                                                                exportedMemoryTypeIndex = ~0U;
2911                 // \note Buffer is only allocated to get memory requirements
2912                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2913                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2914                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2915
2916                 if (config.hostVisible)
2917                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2918
2919                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
2920                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
2921                 const int                                                               newFd                   (dup2(fd.getFd(), secondFd.getFd()));
2922
2923                 if (newFd < 0)
2924                         log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2925
2926                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
2927
2928                 {
2929                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
2930
2931                         if (config.hostVisible)
2932                         {
2933                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 99012346u, (size_t)bufferSize));
2934
2935                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
2936
2937                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
2938                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
2939                         }
2940                 }
2941
2942                 return tcu::TestStatus::pass("Pass");
2943         }
2944 #else
2945         DE_UNREF(context);
2946         DE_UNREF(config);
2947         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2948 #endif
2949 }
2950
2951 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
2952 {
2953 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2954         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2955         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, config.externalType, 0u));
2956         const vk::InstanceDriver                        vki                                     (vkp, *instance);
2957         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2958         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2959
2960         {
2961                 const vk::Unique<vk::VkDevice>                  device                  (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2962                 const vk::DeviceDriver                                  vkd                             (vki, *device);
2963
2964                 TestLog&                                                                log                             = context.getTestContext().getLog();
2965                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2966                 const vk::VkDeviceSize                                  bufferSize              = 1024;
2967                 const deUint32                                                  seed                    = 2554088961u;
2968                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
2969
2970                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2971
2972                 deUint32                                                                exportedMemoryTypeIndex = ~0U;
2973                 // \note Buffer is only allocated to get memory requirements
2974                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2975                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
2976                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2977
2978                 if (config.hostVisible)
2979                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2980
2981                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
2982                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
2983                 const int                                                               newFd                   (dup3(fd.getFd(), secondFd.getFd(), 0));
2984
2985                 if (newFd < 0)
2986                         log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2987
2988                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
2989
2990                 {
2991                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
2992
2993                         if (config.hostVisible)
2994                         {
2995                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
2996
2997                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
2998
2999                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3000                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3001                         }
3002                 }
3003
3004                 return tcu::TestStatus::pass("Pass");
3005         }
3006 #else
3007         DE_UNREF(context);
3008         DE_UNREF(config);
3009         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3010 #endif
3011 }
3012
3013 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3014 {
3015 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3016         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
3017         const vk::Unique<vk::VkInstance>                        instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3018         const vk::InstanceDriver                                        vki                                     (vkp, *instance);
3019         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3020         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3021
3022         {
3023                 const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3024                 const vk::DeviceDriver                                  vkd                                     (vki, *device);
3025
3026                 TestLog&                                                                log                                     = context.getTestContext().getLog();
3027                 const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3028                 const vk::VkDeviceSize                                  bufferSize                      = 1024;
3029                 const deUint32                                                  seed                            = 3403586456u;
3030                 const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
3031
3032                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3033
3034                 deUint32                                                                exportedMemoryTypeIndex = ~0U;
3035                 // \note Buffer is only allocated to get memory requirements
3036                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3037                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3038                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3039
3040                 if (config.hostVisible)
3041                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3042
3043                 const NativeHandle                                              fd                                      (getMemoryFd(vkd, *device, *memory, config.externalType));
3044
3045                 {
3046                         int sv[2];
3047
3048                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3049                         {
3050                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3051                                 TCU_FAIL("Failed to create socket pair");
3052                         }
3053
3054                         {
3055                                 const NativeHandle      srcSocket       (sv[0]);
3056                                 const NativeHandle      dstSocket       (sv[1]);
3057                                 std::string                     sendData        ("deqp");
3058
3059                                 // Send FD
3060                                 {
3061                                         const int                       fdRaw   (fd.getFd());
3062                                         msghdr                          msg;
3063                                         cmsghdr*                        cmsg;
3064                                         char                            tmpBuffer[CMSG_SPACE(sizeof(int))];
3065                                         iovec                           iov             = { &sendData[0], sendData.length()};
3066
3067                                         deMemset(&msg, 0, sizeof(msg));
3068
3069                                         msg.msg_control         = tmpBuffer;
3070                                         msg.msg_controllen      = sizeof(tmpBuffer);
3071                                         msg.msg_iovlen          = 1;
3072                                         msg.msg_iov                     = &iov;
3073
3074                                         cmsg                            = CMSG_FIRSTHDR(&msg);
3075                                         cmsg->cmsg_level        = SOL_SOCKET;
3076                                         cmsg->cmsg_type         = SCM_RIGHTS;
3077                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
3078
3079                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3080                                         msg.msg_controllen = cmsg->cmsg_len;
3081
3082                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3083                                         {
3084                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3085                                                 TCU_FAIL("Failed to send fd over socket");
3086                                         }
3087                                 }
3088
3089                                 // Recv FD
3090                                 {
3091                                         msghdr                  msg;
3092                                         char                    tmpBuffer[CMSG_SPACE(sizeof(int))];
3093                                         std::string             recvData        (4, '\0');
3094                                         iovec                   iov                     = { &recvData[0], recvData.length() };
3095
3096                                         deMemset(&msg, 0, sizeof(msg));
3097
3098                                         msg.msg_control         = tmpBuffer;
3099                                         msg.msg_controllen      = sizeof(tmpBuffer);
3100                                         msg.msg_iovlen          = 1;
3101                                         msg.msg_iov                     = &iov;
3102
3103                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3104
3105                                         if (bytes < 0)
3106                                         {
3107                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3108                                                 TCU_FAIL("Failed to recv fd over socket");
3109
3110                                         }
3111                                         else if (bytes != (ssize_t)sendData.length())
3112                                         {
3113                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3114                                         }
3115                                         else
3116                                         {
3117                                                 const cmsghdr* const    cmsg    = CMSG_FIRSTHDR(&msg);
3118                                                 int                                             newFd_;
3119                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3120                                                 NativeHandle                    newFd   (newFd_);
3121
3122                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3123                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3124                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3125                                                 TCU_CHECK(recvData == sendData);
3126                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3127
3128                                                 {
3129                                                         const vk::Unique<vk::VkDeviceMemory> newMemory (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3130
3131                                                         if (config.hostVisible)
3132                                                         {
3133                                                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3134
3135                                                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3136
3137                                                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3138                                                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3139                                                         }
3140                                                 }
3141                                         }
3142                                 }
3143                         }
3144                 }
3145         }
3146
3147         return tcu::TestStatus::pass("Pass");
3148 #else
3149         DE_UNREF(context);
3150         DE_UNREF(config);
3151         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3152 #endif
3153 }
3154
3155 struct BufferTestConfig
3156 {
3157                                                                                                 BufferTestConfig        (vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType_,
3158                                                                                                                                          bool                                                                           dedicated_)
3159                 : externalType  (externalType_)
3160                 , dedicated             (dedicated_)
3161         {
3162         }
3163
3164         vk::VkExternalMemoryHandleTypeFlagBitsKHR       externalType;
3165         bool                                                                            dedicated;
3166 };
3167
3168 tcu::TestStatus testBufferBindExportImportBind (Context&                                context,
3169                                                                                                 const BufferTestConfig  config)
3170 {
3171         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3172         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3173         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3174         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3175         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3176         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3177         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3178         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3179         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3180
3181         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3182
3183         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3184         // \note Buffer is only allocated to get memory requirements
3185         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3186         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3187         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3188         NativeHandle                                                    handle;
3189
3190         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3191
3192         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3193
3194         {
3195                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3196                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3197
3198                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3199         }
3200
3201         return tcu::TestStatus::pass("Pass");
3202 }
3203
3204 tcu::TestStatus testBufferExportBindImportBind (Context&                                context,
3205                                                                                                 const BufferTestConfig  config)
3206 {
3207         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3208         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3209         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3210         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3211         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3212         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3213         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3214         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3215         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3216
3217         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3218
3219         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3220         // \note Buffer is only allocated to get memory requirements
3221         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3222         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3223         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3224         NativeHandle                                                    handle;
3225
3226         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3227         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3228
3229         {
3230                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3231                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3232
3233                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3234         }
3235
3236         return tcu::TestStatus::pass("Pass");
3237 }
3238
3239 tcu::TestStatus testBufferExportImportBindBind (Context&                                context,
3240                                                                                                 const BufferTestConfig  config)
3241 {
3242         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3243         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3244         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3245         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3246         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3247         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3248         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3249         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3250         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3251
3252         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3253
3254         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3255         // \note Buffer is only allocated to get memory requirements
3256         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3257         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3258         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3259         NativeHandle                                                    handle;
3260
3261         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3262
3263         {
3264                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3265                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3266
3267                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3268                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3269         }
3270
3271         return tcu::TestStatus::pass("Pass");
3272 }
3273
3274 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
3275 {
3276         const vk::VkImageCreateFlags            createFlags[]           =
3277         {
3278                 0u,
3279                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3280                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3281                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3282                 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3283                 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
3284                 vk::VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR
3285         };
3286         const vk::VkImageUsageFlags                     usageFlags[]            =
3287         {
3288                 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3289                 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3290                 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3291                 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3292                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3293                 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3294                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
3295                 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3296         };
3297         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3298         const vk::Unique<vk::VkInstance>        instance                        (createInstance(vkp, 0u, externalType, 0u));
3299         const vk::InstanceDriver                        vki                                     (vkp, *instance);
3300         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3301         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3302         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3303
3304         // VkDevice is only created if physical device claims to support any of these types.
3305         vk::Move<vk::VkDevice>                          device;
3306         de::MovePtr<vk::DeviceDriver>           vkd;
3307         bool                                                            deviceHasDedicated      = false;
3308
3309         TestLog&                                                        log                                     = context.getTestContext().getLog();
3310
3311         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3312         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3313         {
3314                 const vk::VkImageViewCreateFlags                                                createFlag              = createFlags[createFlagNdx];
3315                 const vk::VkImageUsageFlags                                                             usageFlag               = usageFlags[usageFlagNdx];
3316                 const vk::VkFormat                                                                              format                  = vk::VK_FORMAT_R8G8B8A8_UNORM;
3317                 const vk::VkImageType                                                                   type                    = vk::VK_IMAGE_TYPE_2D;
3318                 const vk::VkImageTiling                                                                 tiling                  = vk::VK_IMAGE_TILING_OPTIMAL;
3319                 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR    externalInfo    =
3320                 {
3321                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
3322                         DE_NULL,
3323                         externalType
3324                 };
3325                 const vk::VkPhysicalDeviceImageFormatInfo2KHR                   info                    =
3326                 {
3327                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
3328                         &externalInfo,
3329
3330                         format,
3331                         type,
3332                         tiling,
3333                         usageFlag,
3334                         createFlag,
3335                 };
3336                 vk::VkExternalImageFormatPropertiesKHR                                  externalProperties      =
3337                 {
3338                         vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
3339                         DE_NULL,
3340                         { 0u, 0u, 0u }
3341                 };
3342                 vk::VkImageFormatProperties2KHR                                                 properties                      =
3343                 {
3344                         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
3345                         &externalProperties,
3346                         {
3347                                 { 0u, 0u, 0u },
3348                                 0u,
3349                                 0u,
3350                                 0u,
3351                                 0u
3352                         }
3353                 };
3354
3355                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3356                         (deviceFeatures.sparseBinding == VK_FALSE))
3357                         continue;
3358
3359                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3360                         (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3361                         continue;
3362
3363                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3364                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3365                         continue;
3366
3367                 vki.getPhysicalDeviceImageFormatProperties2KHR(physicalDevice, &info, &properties);
3368
3369                 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3370                 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR);
3371                 TCU_CHECK(externalProperties.pNext == DE_NULL);
3372                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3373
3374                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)) != 0)
3375                 {
3376                         const bool      requiresDedicated       = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
3377
3378                         if (!device || (requiresDedicated && !deviceHasDedicated))
3379                         {
3380                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3381                                 try
3382                                 {
3383                                         device                          = createDevice(vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3384                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vki, *device));
3385                                         deviceHasDedicated      = requiresDedicated;
3386                                 }
3387                                 catch (const tcu::NotSupportedError& e)
3388                                 {
3389                                         log << e;
3390                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3391                                 }
3392                         }
3393                 }
3394
3395                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) != 0)
3396                 {
3397                         DE_ASSERT(!!device);
3398                         DE_ASSERT(vkd);
3399
3400                         if (deviceHasDedicated)
3401                         {
3402                                 const vk::Unique<vk::VkImage>                           image                                           (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3403                                 const vk::VkMemoryDedicatedRequirementsKHR      reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *image));
3404                                 const bool                                                                      propertiesRequiresDedicated     = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0;
3405                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
3406
3407                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
3408                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3409                         }
3410                         else
3411                         {
3412                                 // We can't query whether dedicated memory is required or not on per-object basis.
3413                                 // This check should be redundant as the code above tries to create device with
3414                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3415                                 // is required. However, checking again doesn't hurt.
3416                                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) == 0);
3417                         }
3418                 }
3419         }
3420
3421         return tcu::TestStatus::pass("Pass");
3422 }
3423
3424 struct ImageTestConfig
3425 {
3426                                                                                                 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType_,
3427                                                                                                                                  bool                                                                           dedicated_)
3428                 : externalType  (externalType_)
3429                 , dedicated             (dedicated_)
3430         {
3431         }
3432
3433         vk::VkExternalMemoryHandleTypeFlagBitsKHR       externalType;
3434         bool                                                                            dedicated;
3435 };
3436
3437 tcu::TestStatus testImageBindExportImportBind (Context&                                 context,
3438                                                                                            const ImageTestConfig        config)
3439 {
3440         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3441         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3442         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3443         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3444         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3445         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3446         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3447         const vk::VkImageUsageFlags                             usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3448         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
3449         const deUint32                                                  width                           = 64u;
3450         const deUint32                                                  height                          = 64u;
3451         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
3452
3453         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3454
3455         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3456         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3457         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA));
3458         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3459         NativeHandle                                                    handle;
3460
3461         VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3462
3463         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3464
3465         {
3466                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3467                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3468
3469                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3470         }
3471
3472         return tcu::TestStatus::pass("Pass");
3473 }
3474
3475 tcu::TestStatus testImageExportBindImportBind (Context&                                 context,
3476                                                                                            const ImageTestConfig        config)
3477 {
3478         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3479         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3480         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3481         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3482         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3483         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3484         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3485         const vk::VkImageUsageFlags                             usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3486         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
3487         const deUint32                                                  width                           = 64u;
3488         const deUint32                                                  height                          = 64u;
3489         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
3490
3491         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3492
3493         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3494         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3495         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA));
3496         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3497         NativeHandle                                                    handle;
3498
3499         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3500         VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3501
3502         {
3503                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3504                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3505
3506                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3507         }
3508
3509         return tcu::TestStatus::pass("Pass");
3510 }
3511
3512 tcu::TestStatus testImageExportImportBindBind (Context&                                 context,
3513                                                                                            const ImageTestConfig        config)
3514 {
3515         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3516         const vk::Unique<vk::VkInstance>                instance                        (createInstance(vkp, 0u, config.externalType, 0u));
3517         const vk::InstanceDriver                                vki                                     (vkp, *instance);
3518         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3519         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3520         const vk::Unique<vk::VkDevice>                  device                          (createDevice(vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3521         const vk::DeviceDriver                                  vkd                                     (vki, *device);
3522         const vk::VkImageUsageFlags                             usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3523         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
3524         const deUint32                                                  width                           = 64u;
3525         const deUint32                                                  height                          = 64u;
3526         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
3527
3528         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3529
3530         deUint32                                                                exportedMemoryTypeIndex = ~0U;
3531         // \note Image is only allocated to get memory requirements
3532         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3533         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA));
3534         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3535         NativeHandle                                                    handle;
3536
3537         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3538
3539         {
3540                 const vk::Unique<vk::VkDeviceMemory>    memoryB (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3541                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3542
3543                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3544                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3545         }
3546
3547         return tcu::TestStatus::pass("Pass");
3548 }
3549 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBitsKHR externalType)
3550 {
3551         const struct
3552         {
3553                 const char* const       name;
3554                 const Permanence        permanence;
3555         } permanences[] =
3556         {
3557                 { "temporary", PERMANENCE_TEMPORARY     },
3558                 { "permanent", PERMANENCE_PERMANENT     }
3559         };
3560
3561         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3562
3563         addFunctionCase(fenceGroup.get(), "info",       "Test external fence queries.", testFenceQueries,       externalType);
3564
3565         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3566         {
3567                 const Permanence                permanence              (permanences[permanenceNdx].permanence);
3568                 const char* const               permanenceName  (permanences[permanenceNdx].name);
3569                 const FenceTestConfig   config                  (externalType, permanence);
3570
3571                 if (!isSupportedPermanence(externalType, permanence))
3572                         continue;
3573
3574                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3575                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3576                 {
3577                         addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName,        "Test creating fence with win32 properties.",   testFenceWin32Create,   config);
3578                 }
3579
3580                 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName,                                "Test importing fence twice.",                                                                                  testFenceImportTwice,                           config);
3581                 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName,                                    "Test importing again over previously imported fence.",                                 testFenceImportReimport,                        config);
3582                 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,               "Test importing fence multiple times.",                                                                 testFenceMultipleImports,                       config);
3583                 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,   "Test signaling, exporting, importing and waiting for the sempahore.",  testFenceSignalExportImportWait,        config);
3584                 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName,                               "Test signaling and importing the fence.",                                                              testFenceSignalImport,                          config);
3585                 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName,                                               "Test resetting the fence.",                                                                                    testFenceReset,                                         config);
3586                 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName,                                "Test fences transference.",                                                                                    testFenceTransference,                          config);
3587
3588                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR
3589                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3590                 {
3591                         // \note Not supported on WIN32 handles
3592                         addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,       "Test exporting fence multiple times.",         testFenceMultipleExports,       config);
3593
3594                         addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName,                                         "Test calling dup() on exported fence.",        testFenceFdDup,                         config);
3595                         addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName,                                        "Test calling dup2() on exported fence.",       testFenceFdDup2,                        config);
3596                         addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName,                                        "Test calling dup3() on exported fence.",       testFenceFdDup3,                        config);
3597                         addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,            "Test sending fence fd over socket.",           testFenceFdSendOverSocket,      config);
3598                 }
3599
3600                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3601                 {
3602                         addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,                  "Test signaling and then waiting for the the sepmahore.",                       testFenceSignalWaitImport,                      config);
3603                         addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,   "Test exporting, signaling, importing and waiting for the fence.",      testFenceExportSignalImportWait,        config);
3604                         addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,   "Test exporting, importing, signaling and waiting for the fence.",      testFenceExportImportSignalWait,        config);
3605                 }
3606         }
3607
3608         return fenceGroup;
3609 }
3610
3611 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
3612 {
3613         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
3614
3615         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR).release());
3616         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3617         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3618         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3619
3620         return fenceGroup;
3621 }
3622
3623 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType)
3624 {
3625         const struct
3626         {
3627                 const char* const       name;
3628                 const Permanence        permanence;
3629         } permanences[] =
3630         {
3631                 { "temporary", PERMANENCE_TEMPORARY     },
3632                 { "permanent", PERMANENCE_PERMANENT     }
3633         };
3634
3635         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
3636
3637         addFunctionCase(semaphoreGroup.get(), "info",   "Test external semaphore queries.",     testSemaphoreQueries,   externalType);
3638
3639         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3640         {
3641                 const Permanence                        permanence              (permanences[permanenceNdx].permanence);
3642                 const char* const                       permanenceName  (permanences[permanenceNdx].name);
3643                 const SemaphoreTestConfig       config                  (externalType, permanence);
3644
3645                 if (!isSupportedPermanence(externalType, permanence))
3646                         continue;
3647
3648                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3649                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3650                 {
3651                         addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,    "Test creating semaphore with win32 properties.",       testSemaphoreWin32Create,       config);
3652                 }
3653
3654                 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName,                            "Test importing semaphore twice.",                                                                              testSemaphoreImportTwice,                               config);
3655                 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName,                                        "Test importing again over previously imported semaphore.",                             testSemaphoreImportReimport,                    config);
3656                 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,           "Test importing semaphore multiple times.",                                                             testSemaphoreMultipleImports,                   config);
3657                 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,       "Test signaling, exporting, importing and waiting for the sempahore.",  testSemaphoreSignalExportImportWait,    config);
3658                 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName,                           "Test signaling and importing the semaphore.",                                                  testSemaphoreSignalImport,                              config);
3659                 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName,                            "Test semaphores transference.",                                                                                testSemaphoreTransference,                              config);
3660
3661                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
3662                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3663                 {
3664                         // \note Not supported on WIN32 handles
3665                         addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,   "Test exporting semaphore multiple times.",             testSemaphoreMultipleExports,   config);
3666
3667                         addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName,                                             "Test calling dup() on exported semaphore.",    testSemaphoreFdDup,                             config);
3668                         addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName,                                    "Test calling dup2() on exported semaphore.",   testSemaphoreFdDup2,                    config);
3669                         addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName,                                    "Test calling dup3() on exported semaphore.",   testSemaphoreFdDup3,                    config);
3670                         addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,                "Test sending semaphore fd over socket.",               testSemaphoreFdSendOverSocket,  config);
3671                 }
3672
3673                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3674                 {
3675                         addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,                      "Test signaling and then waiting for the the sepmahore.",                               testSemaphoreSignalWaitImport,                  config);
3676                         addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,       "Test exporting, signaling, importing and waiting for the semaphore.",  testSemaphoreExportSignalImportWait,    config);
3677                         addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,       "Test exporting, importing, signaling and waiting for the semaphore.",  testSemaphoreExportImportSignalWait,    config);
3678                 }
3679         }
3680
3681         return semaphoreGroup;
3682 }
3683
3684 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
3685 {
3686         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
3687
3688         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR).release());
3689         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3690         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3691         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3692
3693         return semaphoreGroup;
3694 }
3695
3696 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType)
3697 {
3698         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
3699
3700         for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
3701         {
3702                 const bool                                              dedicated               (dedicatedNdx == 1);
3703                 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup  (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
3704
3705                 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
3706                 {
3707                         const bool                                              hostVisible                     (hostVisibleNdx == 1);
3708                         de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup        (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
3709                         const MemoryTestConfig                  memoryConfig            (externalType, hostVisible, dedicated);
3710
3711                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
3712                                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
3713                         {
3714                                 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .",         testMemoryWin32Create,  memoryConfig);
3715                         }
3716
3717                         addFunctionCase(hostVisibleGroup.get(), "import_twice",                         "Test importing memory object twice.",                  testMemoryImportTwice,          memoryConfig);
3718                         addFunctionCase(hostVisibleGroup.get(), "import_multiple_times",        "Test importing memory object multiple times.", testMemoryMultimpleImports,     memoryConfig);
3719
3720                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
3721                         {
3722                                 addFunctionCase(hostVisibleGroup.get(), "dup",                                                                  "Test calling dup() on exported memory.",       testMemoryFdDup,                        memoryConfig);
3723                                 addFunctionCase(hostVisibleGroup.get(), "dup2",                                                                 "Test calling dup2() on exported memory.",      testMemoryFdDup2,                       memoryConfig);
3724                                 addFunctionCase(hostVisibleGroup.get(), "dup3",                                                                 "Test calling dup3() on exported memory.",      testMemoryFdDup3,                       memoryConfig);
3725                                 addFunctionCase(hostVisibleGroup.get(), "send_over_socket",                                             "Test sending memory fd over socket.",          testMemoryFdSendOverSocket,     memoryConfig);
3726                                 // \note Not supported on WIN32 handles
3727                                 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times",                                "Test exporting memory multiple times.",        testMemoryMultimpleExports,     memoryConfig);
3728                         }
3729
3730                         dedicatedGroup->addChild(hostVisibleGroup.release());
3731                 }
3732
3733                 {
3734                         de::MovePtr<tcu::TestCaseGroup> bufferGroup             (new tcu::TestCaseGroup(testCtx, "buffer", ""));
3735                         const BufferTestConfig                  bufferConfig    (externalType, dedicated);
3736
3737                         addFunctionCase(bufferGroup.get(), "info",                                              "External buffer memory info query.",                                           testBufferQueries,                              externalType);
3738                         addFunctionCase(bufferGroup.get(), "bind_export_import_bind",   "Test binding, exporting, importing and binding buffer.",       testBufferBindExportImportBind, bufferConfig);
3739                         addFunctionCase(bufferGroup.get(), "export_bind_import_bind",   "Test exporting, binding, importing and binding buffer.",       testBufferExportBindImportBind, bufferConfig);
3740                         addFunctionCase(bufferGroup.get(), "export_import_bind_bind",   "Test exporting, importind and binding buffer.",                        testBufferExportImportBindBind, bufferConfig);
3741
3742                         dedicatedGroup->addChild(bufferGroup.release());
3743                 }
3744
3745                 {
3746                         de::MovePtr<tcu::TestCaseGroup> imageGroup      (new tcu::TestCaseGroup(testCtx, "image", ""));
3747                         const ImageTestConfig                   imageConfig     (externalType, dedicated);
3748
3749                         addFunctionCase(imageGroup.get(), "info",                                               "External image memory info query.",                                            testImageQueries,                               externalType);
3750                         addFunctionCase(imageGroup.get(), "bind_export_import_bind",    "Test binding, exporting, importing and binding image.",        testImageBindExportImportBind,  imageConfig);
3751                         addFunctionCase(imageGroup.get(), "export_bind_import_bind",    "Test exporting, binding, importing and binding image.",        testImageExportBindImportBind,  imageConfig);
3752                         addFunctionCase(imageGroup.get(), "export_import_bind_bind",    "Test exporting, importind and binding image.",                         testImageExportImportBindBind,  imageConfig);
3753
3754                         dedicatedGroup->addChild(imageGroup.release());
3755                 }
3756
3757                 group->addChild(dedicatedGroup.release());
3758         }
3759
3760         return group;
3761 }
3762
3763 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
3764 {
3765         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
3766
3767         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR).release());
3768         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR).release());
3769         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR).release());
3770
3771         return group;
3772 }
3773
3774 } // anonymous
3775
3776 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
3777 {
3778         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
3779
3780         group->addChild(createSemaphoreTests(testCtx).release());
3781         group->addChild(createMemoryTests(testCtx).release());
3782         group->addChild(createFenceTests(testCtx).release());
3783
3784         return group.release();
3785 }
3786
3787 } // api
3788 } // vkt