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