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