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