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