acdc1abd3d61c9209c7caccad56e3b6e4517cc29
[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 #include "vktCustomInstancesDevices.hpp"
24 #include "../compute/vktComputeTestsUtil.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkDeviceUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkApiVersion.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkBufferWithMemory.hpp"
38
39 #include "tcuTestLog.hpp"
40 #include "tcuCommandLine.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
45
46 #include "deMemory.h"
47
48 #include "vktExternalMemoryUtil.hpp"
49
50 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
51 #       include <unistd.h>
52 #       include <fcntl.h>
53 #       include <errno.h>
54 #       include <sys/types.h>
55 #       include <sys/socket.h>
56 #endif
57
58 #if (DE_OS == DE_OS_WIN32)
59 #       define WIN32_LEAN_AND_MEAN
60 #       include <windows.h>
61 #       include <dxgi1_2.h>
62 #endif
63
64 #include <chrono>
65
66 using tcu::TestLog;
67 using namespace vkt::ExternalMemoryUtil;
68
69 namespace vkt
70 {
71 namespace api
72 {
73 namespace
74 {
75
76
77 template<typename T, int size>
78 T multiplyComponents (const tcu::Vector<T, size>& v)
79 {
80         T accum = 1;
81         for (int i = 0; i < size; ++i)
82                 accum *= v[i];
83         return accum;
84 }
85
86 std::string getFormatCaseName (vk::VkFormat format)
87 {
88         return de::toLower(de::toString(getFormatStr(format)).substr(10));
89 }
90
91 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface&    vkd,
92                                                                                                                                   vk::VkDevice                                  device,
93                                                                                                                                   vk::VkBuffer                                  buffer)
94 {
95         const vk::VkBufferMemoryRequirementsInfo2       requirementInfo                 =
96         {
97                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
98                 DE_NULL,
99                 buffer
100         };
101         vk::VkMemoryDedicatedRequirements                       dedicatedRequirements   =
102         {
103                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
104                 DE_NULL,
105                 VK_FALSE,
106                 VK_FALSE
107         };
108         vk::VkMemoryRequirements2                                       requirements                    =
109         {
110                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
111                 &dedicatedRequirements,
112                 { 0u, 0u, 0u }
113         };
114
115         vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
116
117         return dedicatedRequirements;
118 }
119
120 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface&    vkd,
121                                                                                                                                   vk::VkDevice                                  device,
122                                                                                                                                   vk::VkImage                                   image)
123 {
124         const vk::VkImageMemoryRequirementsInfo2        requirementInfo         =
125         {
126                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
127                 DE_NULL,
128                 image
129         };
130         vk::VkMemoryDedicatedRequirements               dedicatedRequirements   =
131         {
132                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
133                 DE_NULL,
134                 VK_FALSE,
135                 VK_FALSE
136         };
137         vk::VkMemoryRequirements2                               requirements                    =
138         {
139                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
140                 &dedicatedRequirements,
141                 { 0u, 0u, 0u }
142         };
143
144         vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
145
146         return dedicatedRequirements;
147 }
148
149 void writeHostMemory (const vk::DeviceInterface&        vkd,
150                                           vk::VkDevice                                  device,
151                                           vk::VkDeviceMemory                    memory,
152                                           size_t                                                size,
153                                           const void*                                   data)
154 {
155         void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
156
157         deMemcpy(ptr, data, size);
158
159         flushMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
160
161         vkd.unmapMemory(device, memory);
162 }
163
164 void checkHostMemory (const vk::DeviceInterface&        vkd,
165                                           vk::VkDevice                                  device,
166                                           vk::VkDeviceMemory                    memory,
167                                           size_t                                                size,
168                                           const void*                                   data)
169 {
170         void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
171
172         invalidateMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
173
174         if (deMemCmp(ptr, data, size) != 0)
175                 TCU_FAIL("Memory contents don't match");
176
177         vkd.unmapMemory(device, memory);
178 }
179
180 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
181 {
182         de::Random                              rng             (seed);
183         std::vector<deUint8>    data    (size);
184
185         for (size_t ndx = 0; ndx < size; ndx++)
186         {
187                 data[ndx] = rng.getUint8();
188         }
189
190         return data;
191 }
192
193 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface&   vki,
194                                                                  vk::VkPhysicalDevice                   device,
195                                                                  vk::VkQueueFlags                               requireFlags)
196 {
197         const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
198
199         for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
200         {
201                 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
202                         return queueFamilyIndex;
203         }
204
205         TCU_THROW(NotSupportedError, "Queue type not supported");
206 }
207
208 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
209                                                                                                 const vk::VkExternalSemaphoreHandleTypeFlags    externalSemaphoreTypes,
210                                                                                                 const vk::VkExternalMemoryHandleTypeFlags               externalMemoryTypes,
211                                                                                                 const vk::VkExternalFenceHandleTypeFlags                externalFenceTypes)
212 {
213         std::vector<std::string> instanceExtensions;
214
215         if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
216                 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
217
218         if (externalSemaphoreTypes != 0)
219                 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
220                         instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
221
222         if (externalMemoryTypes != 0)
223                 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
224                         instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
225
226         if (externalFenceTypes != 0)
227                 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
228                         instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
229
230         return instanceExtensions;
231 }
232
233 CustomInstance createTestInstance (Context&                                                                             context,
234                                                                    const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
235                                                                    const vk::VkExternalMemoryHandleTypeFlags    externalMemoryTypes,
236                                                                    const vk::VkExternalFenceHandleTypeFlags             externalFenceTypes)
237 {
238         try
239         {
240                 return vkt::createCustomInstanceWithExtensions(context, getInstanceExtensions(context.getUsedApiVersion(), externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
241         }
242         catch (const vk::Error& error)
243         {
244                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
245                         TCU_THROW(NotSupportedError, "Required extensions not supported");
246
247                 throw;
248         }
249 }
250
251 vk::Move<vk::VkDevice> createTestDevice (const Context&                                                                 context,
252                                                                                  const vk::PlatformInterface&                                   vkp,
253                                                                                  vk::VkInstance                                                                 instance,
254                                                                                  const vk::InstanceInterface&                                   vki,
255                                                                                  vk::VkPhysicalDevice                                                   physicalDevice,
256                                                                                  const vk::VkExternalSemaphoreHandleTypeFlags   externalSemaphoreTypes,
257                                                                                  const vk::VkExternalMemoryHandleTypeFlags              externalMemoryTypes,
258                                                                                  const vk::VkExternalFenceHandleTypeFlags               externalFenceTypes,
259                                                                                  deUint32                                                                               queueFamilyIndex,
260                                                                                  bool                                                                                   useDedicatedAllocs = false,
261                                                                                  void * protectedFeatures = DE_NULL)
262 {
263         const deUint32                          apiVersion                              = context.getUsedApiVersion();
264         bool                                            useExternalSemaphore    = false;
265         bool                                            useExternalFence                = false;
266         bool                                            useExternalMemory               = false;
267         std::vector<const char*>        deviceExtensions;
268
269         if ((externalSemaphoreTypes
270                         & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
271                                 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
272         {
273                 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
274                 useExternalSemaphore = true;
275         }
276
277         if ((externalFenceTypes
278                         & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
279                                 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
280         {
281                 deviceExtensions.push_back("VK_KHR_external_fence_fd");
282                 useExternalFence = true;
283         }
284
285         if (useDedicatedAllocs)
286         {
287                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
288                         deviceExtensions.push_back("VK_KHR_dedicated_allocation");
289                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
290                         deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
291         }
292
293         if ((externalMemoryTypes
294                         & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
295                                 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
296         {
297                 deviceExtensions.push_back("VK_KHR_external_memory_fd");
298                 useExternalMemory = true;
299         }
300
301         if ((externalMemoryTypes
302                         & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
303         {
304                 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
305                 useExternalMemory = true;
306         }
307
308         if ((externalSemaphoreTypes
309                         & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
310                                 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
311         {
312                 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
313                 useExternalSemaphore = true;
314         }
315
316         if ((externalFenceTypes
317                         & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
318                                 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
319         {
320                 deviceExtensions.push_back("VK_KHR_external_fence_win32");
321                 useExternalFence = true;
322         }
323
324         if ((externalMemoryTypes
325                         & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
326                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
327                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
328                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
329                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
330                            | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
331         {
332                 deviceExtensions.push_back("VK_KHR_external_memory_win32");
333                 useExternalMemory = true;
334         }
335
336         if ((externalMemoryTypes
337                 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
338         {
339                 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
340                 useExternalMemory = true;
341                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
342                         deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
343                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
344                         deviceExtensions.push_back("VK_EXT_queue_family_foreign");
345         }
346
347         if (useExternalSemaphore)
348         {
349                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
350                         deviceExtensions.push_back("VK_KHR_external_semaphore");
351         }
352
353         if (useExternalFence)
354         {
355                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
356                         deviceExtensions.push_back("VK_KHR_external_fence");
357         }
358
359         if (useExternalMemory)
360         {
361                 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
362                         deviceExtensions.push_back("VK_KHR_external_memory");
363         }
364
365         const float                                                             priority                                = 0.5f;
366         const vk::VkDeviceQueueCreateInfo               queues[]                                =
367         {
368                 {
369                         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
370                         DE_NULL,
371                         0u,
372
373                         queueFamilyIndex,
374                         1u,
375                         &priority
376                 }
377         };
378         const vk::VkDeviceCreateInfo                    deviceCreateInfo                =
379         {
380                 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
381                 protectedFeatures,
382                 0u,
383
384                 DE_LENGTH_OF_ARRAY(queues),
385                 queues,
386
387                 0u,
388                 DE_NULL,
389
390                 (deUint32)deviceExtensions.size(),
391                 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
392                 DE_NULL
393         };
394
395         try
396         {
397                 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
398         }
399         catch (const vk::Error& error)
400         {
401                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
402                         TCU_THROW(NotSupportedError, "Required extensions not supported");
403
404                 throw;
405         }
406 }
407
408 vk::VkQueue getQueue (const vk::DeviceInterface&        vkd,
409                                           vk::VkDevice                                  device,
410                                           deUint32                                              queueFamilyIndex)
411 {
412         vk::VkQueue queue;
413
414         vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
415
416         return queue;
417 }
418
419 uint32_t getMaxInvocations(const Context& context, uint32_t idx)
420 {
421         const auto&     vki                             = context.getInstanceInterface();
422         const auto      physicalDevice  = context.getPhysicalDevice();
423         const auto      properties              = vk::getPhysicalDeviceProperties(vki, physicalDevice);
424
425         return properties.limits.maxComputeWorkGroupSize[idx];
426 }
427
428 void checkSemaphoreSupport (const vk::InstanceInterface&                                vki,
429                                                         vk::VkPhysicalDevice                                            device,
430                                                         vk::VkExternalSemaphoreHandleTypeFlagBits       externalType)
431 {
432         const vk::VkPhysicalDeviceExternalSemaphoreInfo info            =
433         {
434                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
435                 DE_NULL,
436                 externalType
437         };
438         vk::VkExternalSemaphoreProperties                               properties      =
439         {
440                 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
441                 DE_NULL,
442                 0u,
443                 0u,
444                 0u
445         };
446
447         vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
448
449         if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
450                 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
451
452         if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
453                 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
454 }
455
456 void checkFenceSupport (const vk::InstanceInterface&                    vki,
457                                                 vk::VkPhysicalDevice                                    device,
458                                                 vk::VkExternalFenceHandleTypeFlagBits   externalType)
459 {
460         const vk::VkPhysicalDeviceExternalFenceInfo     info            =
461         {
462                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
463                 DE_NULL,
464                 externalType
465         };
466         vk::VkExternalFenceProperties                           properties      =
467         {
468                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
469                 DE_NULL,
470                 0u,
471                 0u,
472                 0u
473         };
474
475         vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
476
477         if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
478                 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
479
480         if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
481                 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
482 }
483
484 void checkBufferSupport (const vk::InstanceInterface&                           vki,
485                                                  vk::VkPhysicalDevice                                           device,
486                                                  vk::VkExternalMemoryHandleTypeFlagBits         externalType,
487                                                  vk::VkBufferViewCreateFlags                            createFlag,
488                                                  vk::VkBufferUsageFlags                                         usageFlag,
489                                                  bool                                                                           dedicated)
490 {
491         const vk::VkPhysicalDeviceExternalBufferInfo    info            =
492         {
493                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
494                 DE_NULL,
495
496                 createFlag,
497                 usageFlag,
498                 externalType
499         };
500         vk::VkExternalBufferProperties                                  properties      =
501         {
502                 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
503                 DE_NULL,
504
505                 { 0u, 0u, 0u }
506         };
507
508         vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
509
510         if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
511                 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
512
513         if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
514                 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
515
516         if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
517                 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
518 }
519
520 void checkImageSupport (const vk::InstanceInterface&                                            vki,
521                                                  vk::VkPhysicalDevice                                                           device,
522                                                  vk::VkExternalMemoryHandleTypeFlagBits                         externalType,
523                                                  vk::VkImageViewCreateFlags                                                     createFlag,
524                                                  vk::VkImageUsageFlags                                                          usageFlag,
525                                                  vk::VkFormat                                                                           format,
526                                                  vk::VkImageTiling                                                                      tiling,
527                                                  bool                                                                                           dedicated)
528 {
529         const vk::VkPhysicalDeviceExternalImageFormatInfo       externalInfo            =
530         {
531                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
532                 DE_NULL,
533                 externalType
534         };
535         const vk::VkPhysicalDeviceImageFormatInfo2                      info                            =
536         {
537                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
538                 &externalInfo,
539
540                 format,
541                 vk::VK_IMAGE_TYPE_2D,
542                 tiling,
543                 usageFlag,
544                 createFlag,
545         };
546         vk::VkExternalImageFormatProperties                                     externalProperties      =
547         {
548                 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
549                 DE_NULL,
550                 { 0u, 0u, 0u }
551         };
552         vk::VkImageFormatProperties2                                            properties                      =
553         {
554                 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
555                 &externalProperties,
556                 {
557                         { 0u, 0u, 0u },
558                         0u,
559                         0u,
560                         0u,
561                         0u
562                 }
563         };
564
565         vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
566
567         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
568                 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
569
570         if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
571                 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
572
573         if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
574                 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
575 }
576
577 void submitEmptySignal (const vk::DeviceInterface&      vkd,
578                                                 vk::VkQueue                                     queue,
579                                                 vk::VkSemaphore                         semaphore)
580 {
581         const vk::VkSubmitInfo submit =
582         {
583                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
584                 DE_NULL,
585
586                 0u,
587                 DE_NULL,
588                 DE_NULL,
589
590                 0u,
591                 DE_NULL,
592
593                 1u,
594                 &semaphore
595         };
596
597         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
598 }
599
600 void tuneWorkSizeYAndPrepareCommandBuffer(  const Context&                                              context,
601                                                                                         const vk::DeviceInterface&                      vk,
602                                                                                         vk::VkDevice                                            device,
603                                                                                         vk::VkQueue                                                     queue,
604                                                                                         vk::VkCommandBuffer                                     cmdBuffer,
605                                                                                         vk::VkDescriptorSet                                     descriptorSet,
606                                                                                         vk::VkPipelineLayout                            pipelineLayout,
607                                                                                         vk::VkPipeline                                          computePipeline,
608                                                                                         vk::VkBufferMemoryBarrier                       computeFinishBarrier,
609                                                                                         vk::VkEvent                                                     event,
610                                                                                         tcu::UVec3*                                                     maxWorkSize)
611
612
613 {
614         // Have it be static so we don't need to do tuning every time, especially for "export_multiple_times" tests.
615         static uint32_t yWorkSize       = 1;
616         uint64_t                timeElapsed = 0;
617         bool                    bOutLoop        = false;
618
619         const vk::Unique<vk::VkFence>   fence(vk::createFence(vk, device));
620
621         const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
622         {
623                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
624                 nullptr,
625                 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
626                 nullptr,
627         };
628
629         while (true) {
630                 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
631
632                 /*
633                  * If the handle type is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, the spec allowed for implementations to return -1
634                  * if the fence is already signaled. Previously, to avoid getting -1 in this case, this test had used vkCmdWaitEvents and
635                  * vkSetEvent after submission to get a proper file descriptor before signaling but it's not invalid to call vkSetEvent
636                  * after submission. So we just use vkCmdSetEvent and check the state of the event after submission to see if it's already
637                  * signaled or an error happens while trying to get a file descriptor.
638                  */
639                 vk.cmdSetEvent(cmdBuffer, event, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
640
641                 // And now we do a simple atomic calculation to avoid signalling instantly right after submit.
642                 vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
643                 //vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
644                 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, nullptr);
645                 vk.cmdDispatch(cmdBuffer, maxWorkSize->x(), yWorkSize, maxWorkSize->z());
646                 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1u, &computeFinishBarrier, 0, nullptr);
647                 vk.endCommandBuffer(cmdBuffer);
648
649                 if (bOutLoop)
650                         break;
651
652                 const vk::VkSubmitInfo submit =
653                 {
654                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
655                         nullptr,
656
657                         0u,
658                         nullptr,
659                         nullptr,
660
661                         1u,
662                         &cmdBuffer,
663
664                         0u,
665                         nullptr
666                 };
667
668                 auto            timeStart               = std::chrono::high_resolution_clock::now();
669
670                 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)*fence));
671                 vk.waitForFences(device, 1u, &fence.get(), true, ~0ull);
672
673                 const auto      executionTime   = std::chrono::high_resolution_clock::now() - timeStart;
674                 auto            elapsed                 = std::chrono::duration_cast<std::chrono::milliseconds>(executionTime);
675
676                 timeElapsed = elapsed.count();
677
678                 // we do loop until we get over 9 miliseconds as an execution time.
679                 if (elapsed.count() > 9)
680                 {
681                         bOutLoop = true;
682                         continue;
683                 }
684
685                 yWorkSize *= 2;
686
687                 if (yWorkSize > maxWorkSize->y())
688                 {
689                         yWorkSize = maxWorkSize->y();
690                         bOutLoop  = true;
691                 }
692
693                 vk.resetCommandBuffer(cmdBuffer, 0u);
694                 vk.resetFences(device, 1u, &*fence);
695         };
696
697         tcu::TestLog& log = context.getTestContext().getLog();
698         log << tcu::TestLog::Message
699                 << "Execution time to get a native file descriptor is " << timeElapsed << "ms with Y WorkSize " << yWorkSize
700                 << tcu::TestLog::EndMessage;
701
702         return;
703 }
704
705 void submitAtomicCalculationsAndGetSemaphoreNative (const Context&                                                                      context,
706                                                                                                         const vk::DeviceInterface&                                              vk,
707                                                                                                         vk::VkDevice                                                                    device,
708                                                                                                         vk::Allocator&                                                                  alloc,
709                                                                                                         vk::VkQueue                                                                             queue,
710                                                                                                         deUint32                                                                                queueFamilyIndex,
711                                                                                                         vk::VkSemaphore                                                                 semaphore,
712                                                                                                         vk::VkExternalSemaphoreHandleTypeFlagBits               externalType,
713                                                                                                         NativeHandle&                                                                   nativeHandle)
714 {
715         const vk::Unique<vk::VkCommandPool>             cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
716         const vk::Unique<vk::VkCommandBuffer>   cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
717
718         const vk::VkEventCreateInfo eventCreateInfo =
719         {
720                 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
721                 nullptr,
722                 0u
723         };
724
725         const vk::Unique<vk::VkEvent>   event(createEvent(vk, device, &eventCreateInfo, nullptr));
726
727         const uint32_t maxXWorkSize             = getMaxInvocations(context, 0);
728         const uint32_t maxYWorkSize             = getMaxInvocations(context, 1);
729
730         tcu::UVec3 workSize                             = { maxXWorkSize, maxYWorkSize, 1u };
731         const uint32_t workGroupCount   = multiplyComponents(workSize);
732
733         const vk::VkDeviceSize                  outputBufferSize =      sizeof(uint32_t) * workGroupCount;
734         const vk::BufferWithMemory              outputBuffer            (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
735
736         // Create a compute shader
737         const vk::Unique<vk::VkShaderModule>    compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
738
739         // Create descriptorSetLayout
740         vk::DescriptorSetLayoutBuilder layoutBuilder;
741         layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
742         vk::Unique<vk::VkDescriptorSetLayout>   descriptorSetLayout(layoutBuilder.build(vk, device));
743
744         // Create compute pipeline
745         const vk::Unique<vk::VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
746         const vk::Unique<vk::VkPipeline>                computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader));
747
748         // Create descriptor pool
749         const vk::Unique<vk::VkDescriptorPool>  descriptorPool(
750                 vk::DescriptorPoolBuilder()
751                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
752                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
753
754
755         const vk::Move<vk::VkDescriptorSet>             descriptorSet                   (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
756         const vk::VkDescriptorBufferInfo                outputBufferInfo                = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
757         const vk::VkBufferMemoryBarrier                 computeFinishBarrier    = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
758
759         vk::DescriptorSetUpdateBuilder()
760                 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
761                 .update(vk, device);
762
763         // Now start tuning work size of Y to have time enough to get a fd at the device.
764         tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
765
766         const vk::VkSubmitInfo submit =
767         {
768                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
769                 nullptr,
770
771                 0u,
772                 nullptr,
773                 nullptr,
774
775                 1u,
776                 &cmdBuffer.get(),
777
778                 1u,
779                 &semaphore
780         };
781
782
783         VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
784
785         getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
786
787         // Allow -1, that is valid if signalled properly.
788         if (nativeHandle.getFd() == -1)
789                 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
790
791         VK_CHECK(vk.queueWaitIdle(queue));
792 }
793
794 void submitEmptyWait (const vk::DeviceInterface&        vkd,
795                                           vk::VkQueue                                   queue,
796                                           vk::VkSemaphore                               semaphore)
797 {
798         const vk::VkPipelineStageFlags  stage   = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
799         const vk::VkSubmitInfo                  submit  =
800         {
801                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
802                 DE_NULL,
803
804                 1u,
805                 &semaphore,
806                 &stage,
807
808                 0u,
809                 DE_NULL,
810
811                 0u,
812                 DE_NULL,
813         };
814
815         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
816 }
817
818 void submitEmptySignal (const vk::DeviceInterface&      vkd,
819                                                 vk::VkQueue                                     queue,
820                                                 vk::VkFence                                     fence)
821 {
822         const vk::VkSubmitInfo submit =
823         {
824                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
825                 DE_NULL,
826
827                 0u,
828                 DE_NULL,
829                 DE_NULL,
830
831                 0u,
832                 DE_NULL,
833
834                 0u,
835                 DE_NULL
836         };
837
838         VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
839 }
840
841 void submitAtomicCalculationsAndGetFenceNative (const Context&                                                          context,
842                                                                                                 const vk::DeviceInterface&                                      vk,
843                                                                                                 vk::VkDevice                                                            device,
844                                                                                                 vk::Allocator&                                                          alloc,
845                                                                                                 vk::VkQueue                                                                     queue,
846                                                                                                 deUint32                                                                        queueFamilyIndex,
847                                                                                                 vk::VkFence                                                                     fence,
848                                                                                                 vk::VkExternalFenceHandleTypeFlagBits           externalType,
849                                                                                                 NativeHandle&                                                           nativeHandle,
850                                                                                                 bool                                                                            expectFenceUnsignaled = true)
851 {
852         const vk::Unique<vk::VkCommandPool>             cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
853         const vk::Unique<vk::VkCommandBuffer>   cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
854
855         const vk::VkEventCreateInfo eventCreateInfo =
856         {
857                 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
858                 DE_NULL,
859                 0u
860         };
861
862         const vk::Unique<vk::VkEvent>   event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
863
864         const uint32_t maxXWorkSize             = getMaxInvocations(context, 0);
865         const uint32_t maxYWorkSize             = getMaxInvocations(context, 1);
866
867         tcu::UVec3 workSize                             = { maxXWorkSize, maxYWorkSize, 1u };
868         const uint32_t workGroupCount   = multiplyComponents(workSize);
869
870         const vk::VkDeviceSize                  outputBufferSize =      sizeof(uint32_t) * workGroupCount;
871         const vk::BufferWithMemory              outputBuffer            (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
872
873         // Create a compute shader
874         const vk::Unique<vk::VkShaderModule>    compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
875
876         // Create descriptorSetLayout
877         vk::DescriptorSetLayoutBuilder layoutBuilder;
878         layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
879         vk::Unique<vk::VkDescriptorSetLayout>   descriptorSetLayout(layoutBuilder.build(vk, device));
880
881         // Create compute pipeline
882         const vk::Unique<vk::VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
883         const vk::Unique<vk::VkPipeline>                computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader));
884
885         // Create descriptor pool
886         const vk::Unique<vk::VkDescriptorPool>  descriptorPool(
887                 vk::DescriptorPoolBuilder()
888                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
889                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
890
891
892         const vk::Move<vk::VkDescriptorSet>             descriptorSet                   (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
893         const vk::VkDescriptorBufferInfo                outputBufferInfo                = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
894         const vk::VkBufferMemoryBarrier                 computeFinishBarrier    = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
895
896         vk::DescriptorSetUpdateBuilder()
897                 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
898                 .update(vk, device);
899
900         // Now start tuning work size of Y to have time enough to get a fd at the device.
901         tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
902
903         const vk::VkSubmitInfo submit =
904         {
905                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
906                 DE_NULL,
907
908                 0u,
909                 DE_NULL,
910                 DE_NULL,
911
912                 1u,
913                 &cmdBuffer.get(),
914
915                 0u,
916                 DE_NULL
917         };
918
919         VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
920
921         getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
922         // Allow -1, that is valid if signalled properly.
923         if (nativeHandle.getFd() == -1)
924                 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
925
926         VK_CHECK(vk.queueWaitIdle(queue));
927 }
928
929 struct TestSemaphoreQueriesParameters
930 {
931         vk::VkSemaphoreType                                                     semaphoreType;
932         vk::VkExternalSemaphoreHandleTypeFlagBits       externalType;
933
934         TestSemaphoreQueriesParameters (vk::VkSemaphoreType                                                     semaphoreType_,
935                                                                         vk::VkExternalSemaphoreHandleTypeFlagBits       externalType_)
936                 : semaphoreType (semaphoreType_)
937                 , externalType  (externalType_)
938         {}
939 };
940
941 tcu::TestStatus testSemaphoreQueries (Context& context, const TestSemaphoreQueriesParameters params)
942 {
943         const CustomInstance                            instance                (createTestInstance(context, params.externalType, 0u, 0u));
944         const vk::InstanceDriver&                       vki                             (instance.getDriver());
945         const vk::VkPhysicalDevice                      device                  (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
946
947         TestLog&                                                        log                             = context.getTestContext().getLog();
948
949         const vk::VkSemaphoreTypeCreateInfo                             semaphoreTypeInfo       =
950         {
951                 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
952                 DE_NULL,
953                 params.semaphoreType,
954                 0,
955         };
956         const vk::VkPhysicalDeviceExternalSemaphoreInfo info                            =
957         {
958                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
959                 &semaphoreTypeInfo,
960                 params.externalType
961         };
962         vk::VkExternalSemaphoreProperties                               properties                      =
963         {
964                 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
965                 DE_NULL,
966                 0u,
967                 0u,
968                 0u
969         };
970
971         vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
972         log << TestLog::Message << properties << TestLog::EndMessage;
973
974         TCU_CHECK(properties.pNext == DE_NULL);
975         TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
976
977         if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
978         {
979                 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
980
981                 if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
982                         return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
983
984                 if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
985                         return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
986         }
987
988         return tcu::TestStatus::pass("Pass");
989 }
990
991 struct SemaphoreTestConfig
992 {
993                                                                                                         SemaphoreTestConfig     (vk::VkExternalSemaphoreHandleTypeFlagBits      externalType_,
994                                                                                                                                                  Permanence                                                                             permanence_)
995                 : externalType          (externalType_)
996                 , permanence            (permanence_)
997         {
998         }
999
1000         vk::VkExternalSemaphoreHandleTypeFlagBits       externalType;
1001         Permanence                                                                      permanence;
1002 };
1003
1004 template<class TestConfig> void initProgramsToGetNativeFd(vk::SourceCollections& dst, const TestConfig)
1005 {
1006         const tcu::IVec3 localSize = { 64, 1, 1 };
1007
1008         std::ostringstream src;
1009         src << "#version 310 es\n"
1010                 << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n"
1011                 << "layout(binding = 0) writeonly buffer Output {\n"
1012                 << "    uint values[];\n"
1013                 << "};\n"
1014                 << "\n"
1015                 << "void main (void) {\n"
1016                 << "    uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1017                 << "\n"
1018                 << "      atomicAdd(values[offset], 1u);\n"
1019                 << "}\n";
1020
1021         dst.glslSources.add("compute") << glu::ComputeSource(src.str());
1022 }
1023
1024 tcu::TestStatus testSemaphoreWin32Create (Context&                                      context,
1025                                                                                   const SemaphoreTestConfig     config)
1026 {
1027 #if (DE_OS == DE_OS_WIN32)
1028         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1029         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1030         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1031         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1032         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1033         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1034
1035         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1036
1037         {
1038                 const vk::Unique<vk::VkDevice>                                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1039                 const vk::DeviceDriver                                                  vkd                             (vkp, instance, *device);
1040                 const vk::VkQueue                                                               queue                   (getQueue(vkd, *device, queueFamilyIndex));
1041                 const vk::VkExportSemaphoreWin32HandleInfoKHR   win32ExportInfo =
1042                 {
1043                         vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
1044                         DE_NULL,
1045
1046                         (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1047                         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1048                         (vk::pt::Win32LPCWSTR)DE_NULL
1049                 };
1050                 const vk::VkExportSemaphoreCreateInfo                   exportCreateInfo=
1051                 {
1052                         vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
1053                         &win32ExportInfo,
1054                         (vk::VkExternalMemoryHandleTypeFlags)config.externalType
1055                 };
1056                 const vk::VkSemaphoreCreateInfo                                 createInfo              =
1057                 {
1058                         vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1059                         &exportCreateInfo,
1060                         0u
1061                 };
1062                 const vk::Unique<vk::VkSemaphore>                               semaphore               (vk::createSemaphore(vkd, *device, &createInfo));
1063
1064                 if (transference == TRANSFERENCE_COPY)
1065                         submitEmptySignal(vkd, queue, *semaphore);
1066
1067                 NativeHandle                                                                    handleA;
1068                 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1069
1070                 {
1071                         const vk::VkSemaphoreImportFlags                        flags                   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1072                         const vk::Unique<vk::VkSemaphore>                       semaphoreA              (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1073
1074                         if (transference == TRANSFERENCE_COPY)
1075                                 submitEmptyWait(vkd, queue, *semaphoreA);
1076                         else if (transference == TRANSFERENCE_REFERENCE)
1077                         {
1078                                 submitEmptySignal(vkd, queue, *semaphore);
1079                                 submitEmptyWait(vkd, queue, *semaphoreA);
1080                         }
1081                         else
1082                                 DE_FATAL("Unknown transference.");
1083
1084                         VK_CHECK(vkd.queueWaitIdle(queue));
1085                 }
1086
1087                 return tcu::TestStatus::pass("Pass");
1088         }
1089 #else
1090         DE_UNREF(context);
1091         DE_UNREF(config);
1092         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1093 #endif
1094 }
1095
1096 tcu::TestStatus testSemaphoreImportTwice (Context&                                      context,
1097                                                                                   const SemaphoreTestConfig     config)
1098 {
1099         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1100         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1101         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1102         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1103         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1104         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1105
1106         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1107
1108         {
1109                 const vk::Unique<vk::VkDevice>          device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1110                 const vk::DeviceDriver                          vkd                             (vkp, instance, *device);
1111                 vk::SimpleAllocator                                     alloc                   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1112                 const vk::VkQueue                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
1113                 const vk::Unique<vk::VkSemaphore>       semaphore               (createExportableSemaphore(vkd, *device, config.externalType));
1114                 NativeHandle                                            handleA;
1115
1116                 if (transference == TRANSFERENCE_COPY)
1117                 {
1118                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
1119                         if (handleA.getFd() == -1)
1120                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1121                 }
1122                 else
1123                         getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1124
1125                 {
1126                         NativeHandle                                            handleB         (handleA);
1127                         const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1128                         const vk::Unique<vk::VkSemaphore>       semaphoreA      (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1129                         const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1130
1131                         if (transference == TRANSFERENCE_COPY)
1132                                 submitEmptyWait(vkd, queue, *semaphoreA);
1133                         else if (transference == TRANSFERENCE_REFERENCE)
1134                         {
1135                                 submitEmptySignal(vkd, queue, *semaphoreA);
1136                                 submitEmptyWait(vkd, queue, *semaphoreB);
1137                         }
1138                         else
1139                                 DE_FATAL("Unknown transference.");
1140
1141                         VK_CHECK(vkd.queueWaitIdle(queue));
1142                 }
1143
1144                 return tcu::TestStatus::pass("Pass");
1145         }
1146 }
1147
1148 tcu::TestStatus testSemaphoreImportReimport (Context&                                   context,
1149                                                                                          const SemaphoreTestConfig      config)
1150 {
1151         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1152         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1153         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1154         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1155         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1156         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1157
1158         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1159
1160         {
1161                 const vk::Unique<vk::VkDevice>          device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1162                 const vk::DeviceDriver                          vkd                             (vkp, instance, *device);
1163                 vk::SimpleAllocator                                     alloc                   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1164                 const vk::VkQueue                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
1165
1166                 const vk::Unique<vk::VkSemaphore>       semaphoreA              (createExportableSemaphore(vkd, *device, config.externalType));
1167                 NativeHandle                                            handleA;
1168
1169                 if (transference == TRANSFERENCE_COPY)
1170                 {
1171                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1172                         if (handleA.getFd() == -1)
1173                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1174                 }
1175                 else
1176                         getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1177
1178                 NativeHandle                                            handleB         (handleA);
1179                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1180                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1181
1182                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
1183
1184                 if (transference == TRANSFERENCE_COPY)
1185                         submitEmptyWait(vkd, queue, *semaphoreB);
1186                 else if (transference == TRANSFERENCE_REFERENCE)
1187                 {
1188                         submitEmptySignal(vkd, queue, *semaphoreA);
1189                         submitEmptyWait(vkd, queue, *semaphoreB);
1190                 }
1191                 else
1192                         DE_FATAL("Unknown transference.");
1193
1194                 VK_CHECK(vkd.queueWaitIdle(queue));
1195
1196                 return tcu::TestStatus::pass("Pass");
1197         }
1198 }
1199
1200 tcu::TestStatus testSemaphoreSignalExportImportWait (Context&                                   context,
1201                                                                                                          const SemaphoreTestConfig      config)
1202 {
1203         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1204         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1205         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1206         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1207         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1208         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1209
1210         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1211
1212         {
1213                 const vk::Unique<vk::VkDevice>          device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1214                 const vk::DeviceDriver                          vkd                                     (vkp, instance, *device);
1215                 vk::SimpleAllocator                                     alloc                           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1216                 const vk::VkQueue                                       queue                           (getQueue(vkd, *device, queueFamilyIndex));
1217                 const vk::Unique<vk::VkSemaphore>       semaphoreA                      (createExportableSemaphore(vkd, *device, config.externalType));
1218                 {
1219                         NativeHandle    handle;
1220
1221                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1222                         if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1223                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1224
1225                         {
1226                                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1227                                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1228                                 submitEmptyWait(vkd, queue, *semaphoreB);
1229
1230                                 VK_CHECK(vkd.queueWaitIdle(queue));
1231                         }
1232                 }
1233
1234                 return tcu::TestStatus::pass("Pass");
1235         }
1236 }
1237
1238 tcu::TestStatus testSemaphoreExportSignalImportWait (Context&                                   context,
1239                                                                                                          const SemaphoreTestConfig      config)
1240 {
1241         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1242         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1243         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1244         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1245         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1246         const vk::VkSemaphoreImportFlags        flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1247
1248         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1249         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1250
1251         {
1252                 const vk::Unique<vk::VkDevice>          device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1253                 const vk::DeviceDriver                          vkd                                     (vkp, instance, *device);
1254                 const vk::VkQueue                                       queue                           (getQueue(vkd, *device, queueFamilyIndex));
1255
1256                 const vk::Unique<vk::VkSemaphore>       semaphoreA                      (createExportableSemaphore(vkd, *device, config.externalType));
1257                 NativeHandle                                            handle;
1258
1259                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1260
1261                 submitEmptySignal(vkd, queue, *semaphoreA);
1262                 {
1263                         {
1264                                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1265
1266                                 submitEmptyWait(vkd, queue, *semaphoreB);
1267                                 VK_CHECK(vkd.queueWaitIdle(queue));
1268                         }
1269                 }
1270
1271                 return tcu::TestStatus::pass("Pass");
1272         }
1273 }
1274
1275 tcu::TestStatus testSemaphoreExportImportSignalWait (Context&                                   context,
1276                                                                                                          const SemaphoreTestConfig      config)
1277 {
1278         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1279         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1280         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1281         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1282         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1283
1284         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1285         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1286
1287         {
1288                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1289                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1290                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1291                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1292
1293                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1294                 NativeHandle                                            handle;
1295
1296                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1297
1298                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1299
1300                 submitEmptySignal(vkd, queue, *semaphoreA);
1301                 submitEmptyWait(vkd, queue, *semaphoreB);
1302
1303                 VK_CHECK(vkd.queueWaitIdle(queue));
1304
1305                 return tcu::TestStatus::pass("Pass");
1306         }
1307 }
1308
1309 tcu::TestStatus testSemaphoreSignalImport (Context&                                             context,
1310                                                                                    const SemaphoreTestConfig    config)
1311 {
1312         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1313         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1314         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1315         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1316         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1317         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1318
1319         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1320
1321         {
1322                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1323                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1324                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1325                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1326                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1327
1328                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1329                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createSemaphore(vkd, *device));
1330                 NativeHandle                                            handle;
1331
1332                 submitEmptySignal(vkd, queue, *semaphoreB);
1333                 VK_CHECK(vkd.queueWaitIdle(queue));
1334
1335                 if (transference == TRANSFERENCE_COPY)
1336                 {
1337                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1338                         if (handle.getFd() == -1)
1339                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1340                 }
1341                 else
1342                         getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1343
1344                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1345
1346                 if (transference == TRANSFERENCE_COPY)
1347                         submitEmptyWait(vkd, queue, *semaphoreB);
1348                 else if (transference == TRANSFERENCE_REFERENCE)
1349                 {
1350                         submitEmptySignal(vkd, queue, *semaphoreA);
1351                         submitEmptyWait(vkd, queue, *semaphoreB);
1352                 }
1353                 else
1354                         DE_FATAL("Unknown transference.");
1355
1356                 VK_CHECK(vkd.queueWaitIdle(queue));
1357
1358                 return tcu::TestStatus::pass("Pass");
1359         }
1360 }
1361
1362 tcu::TestStatus testSemaphoreSignalWaitImport (Context&                                         context,
1363                                                                                            const SemaphoreTestConfig    config)
1364 {
1365         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1366         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1367         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1368         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1369         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1370
1371         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1372
1373         {
1374                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1375                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1376                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1377                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1378
1379                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1380                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createSemaphore(vkd, *device));
1381                 NativeHandle                                            handle;
1382
1383                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1384
1385                 submitEmptySignal(vkd, queue, *semaphoreB);
1386                 submitEmptyWait(vkd, queue, *semaphoreB);
1387
1388                 VK_CHECK(vkd.queueWaitIdle(queue));
1389
1390                 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1391
1392                 submitEmptySignal(vkd, queue, *semaphoreA);
1393                 submitEmptyWait(vkd, queue, *semaphoreB);
1394
1395                 VK_CHECK(vkd.queueWaitIdle(queue));
1396
1397                 return tcu::TestStatus::pass("Pass");
1398         }
1399 }
1400
1401 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context&                                             context,
1402                                                                                                    const SemaphoreTestConfig    config)
1403 {
1404         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1405         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1406         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1407         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1408         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1409         const vk::VkSemaphoreImportFlags        flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1410
1411         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1412
1413         {
1414                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1415                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1416                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1417                 NativeHandle                                            handle          = -1;
1418                 const vk::Unique<vk::VkSemaphore>       semaphore       (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1419
1420                 submitEmptyWait(vkd, queue, *semaphore);
1421                 VK_CHECK(vkd.queueWaitIdle(queue));
1422
1423                 return tcu::TestStatus::pass("Pass");
1424         }
1425 }
1426
1427 tcu::TestStatus testSemaphoreMultipleExports (Context&                                  context,
1428                                                                                           const SemaphoreTestConfig     config)
1429 {
1430         const size_t                                            exportCount                     = 1024;
1431         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1432         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1433         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1434         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1435         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1436         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1437
1438         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1439
1440         {
1441                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1442                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1443                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1444                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1445                 const vk::Unique<vk::VkSemaphore>       semaphore       (createExportableSemaphore(vkd, *device, config.externalType));
1446
1447                 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1448                 {
1449                         NativeHandle handle;
1450
1451                         // Need to touch watchdog due to how long one iteration takes
1452                         context.getTestContext().touchWatchdog();
1453
1454                         if (transference == TRANSFERENCE_COPY)
1455                         {
1456                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1457                                 if (handle.getFd() == -1)
1458                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1459                         }
1460                         else
1461                                 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1462                 }
1463
1464                 submitEmptySignal(vkd, queue, *semaphore);
1465                 submitEmptyWait(vkd, queue, *semaphore);
1466
1467                 VK_CHECK(vkd.queueWaitIdle(queue));
1468         }
1469
1470         return tcu::TestStatus::pass("Pass");
1471 }
1472
1473 tcu::TestStatus testSemaphoreMultipleImports (Context&                                  context,
1474                                                                                           const SemaphoreTestConfig     config)
1475 {
1476         const size_t                                            importCount                     = 4 * 1024;
1477         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1478         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1479         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1480         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1481         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1482         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1483
1484         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1485
1486         {
1487                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1488                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1489                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1490                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1491                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1492                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1493                 NativeHandle                                            handleA;
1494
1495                 if (transference == TRANSFERENCE_COPY)
1496                 {
1497                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1498                         if (handleA.getFd() == -1)
1499                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1500                 }
1501                 else
1502                         getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1503
1504                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1505                 {
1506                         NativeHandle                                            handleB         (handleA);
1507                         const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1508                 }
1509
1510                 if (transference == TRANSFERENCE_COPY)
1511                 {
1512                         importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1513                         submitEmptyWait(vkd, queue, *semaphoreA);
1514                 }
1515                 else if (transference == TRANSFERENCE_REFERENCE)
1516                 {
1517                         submitEmptySignal(vkd, queue, *semaphoreA);
1518                         submitEmptyWait(vkd, queue, *semaphoreA);
1519                 }
1520                 else
1521                         DE_FATAL("Unknown transference.");
1522
1523                 VK_CHECK(vkd.queueWaitIdle(queue));
1524         }
1525
1526         return tcu::TestStatus::pass("Pass");
1527 }
1528
1529 tcu::TestStatus testSemaphoreTransference (Context&                                             context,
1530                                                                                    const SemaphoreTestConfig    config)
1531 {
1532         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1533         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1534         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1535         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1536         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1537         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1538
1539         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1540
1541         {
1542                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1543                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context,  vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1544                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1545                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1546                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1547
1548                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1549                 NativeHandle                                            handle;
1550
1551                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1552                 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1553                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1554
1555                 {
1556                         const vk::Unique<vk::VkSemaphore>       semaphoreB                      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1557
1558                         if (config.permanence == PERMANENCE_PERMANENT)
1559                         {
1560                                 if (transference == TRANSFERENCE_COPY)
1561                                 {
1562                                         submitEmptySignal(vkd, queue, *semaphoreA);
1563                                         submitEmptyWait(vkd, queue, *semaphoreB);
1564                                         VK_CHECK(vkd.queueWaitIdle(queue));
1565
1566                                         submitEmptySignal(vkd, queue, *semaphoreB);
1567
1568                                         submitEmptyWait(vkd, queue, *semaphoreA);
1569                                         submitEmptyWait(vkd, queue, *semaphoreB);
1570                                         VK_CHECK(vkd.queueWaitIdle(queue));
1571                                 }
1572                                 else if (transference== TRANSFERENCE_REFERENCE)
1573                                 {
1574                                         submitEmptyWait(vkd, queue, *semaphoreB);
1575                                         VK_CHECK(vkd.queueWaitIdle(queue));
1576
1577                                         submitEmptySignal(vkd, queue, *semaphoreA);
1578                                         submitEmptyWait(vkd, queue, *semaphoreB);
1579
1580                                         submitEmptySignal(vkd, queue, *semaphoreB);
1581                                         submitEmptyWait(vkd, queue, *semaphoreA);
1582                                         VK_CHECK(vkd.queueWaitIdle(queue));
1583                                 }
1584                                 else
1585                                         DE_FATAL("Unknown transference.");
1586                         }
1587                         else if (config.permanence == PERMANENCE_TEMPORARY)
1588                         {
1589                                 if (transference == TRANSFERENCE_COPY)
1590                                 {
1591                                         submitEmptySignal(vkd, queue, *semaphoreA);
1592                                         submitEmptyWait(vkd, queue, *semaphoreB);
1593                                         VK_CHECK(vkd.queueWaitIdle(queue));
1594
1595                                         submitEmptySignal(vkd, queue, *semaphoreB);
1596
1597                                         submitEmptyWait(vkd, queue, *semaphoreA);
1598                                         submitEmptyWait(vkd, queue, *semaphoreB);
1599                                         VK_CHECK(vkd.queueWaitIdle(queue));
1600                                 }
1601                                 else if (transference== TRANSFERENCE_REFERENCE)
1602                                 {
1603                                         submitEmptyWait(vkd, queue, *semaphoreB);
1604                                         VK_CHECK(vkd.queueWaitIdle(queue));
1605
1606                                         submitEmptySignal(vkd, queue, *semaphoreA);
1607                                         submitEmptySignal(vkd, queue, *semaphoreB);
1608
1609                                         submitEmptyWait(vkd, queue, *semaphoreB);
1610                                         submitEmptyWait(vkd, queue, *semaphoreA);
1611                                         VK_CHECK(vkd.queueWaitIdle(queue));
1612                                 }
1613                                 else
1614                                         DE_FATAL("Unknown transference.");
1615                         }
1616                         else
1617                                 DE_FATAL("Unknown permanence.");
1618                 }
1619
1620                 return tcu::TestStatus::pass("Pass");
1621         }
1622 }
1623
1624 tcu::TestStatus testSemaphoreFdDup (Context&                                    context,
1625                                                                         const SemaphoreTestConfig       config)
1626 {
1627 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1628         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1629         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1630         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1631         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1632         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1633         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1634
1635         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1636
1637         {
1638                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1639                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1640                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1641                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1642                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1643
1644                 TestLog&                                                        log                     = context.getTestContext().getLog();
1645                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1646
1647                 {
1648                         NativeHandle            fd;
1649
1650                         if (transference == TRANSFERENCE_COPY)
1651                         {
1652                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1653                                 if (fd.getFd() == -1)
1654                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1655                         }
1656                         else
1657                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1658
1659                         NativeHandle            newFd   (dup(fd.getFd()));
1660
1661                         if (newFd.getFd() < 0)
1662                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1663
1664                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1665
1666                         {
1667                                 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1668
1669                                 if (transference == TRANSFERENCE_COPY)
1670                                         submitEmptyWait(vkd, queue, *semaphoreB);
1671                                 else if (transference == TRANSFERENCE_REFERENCE)
1672                                 {
1673                                         submitEmptySignal(vkd, queue, *semaphoreA);
1674                                         submitEmptyWait(vkd, queue, *semaphoreB);
1675                                 }
1676                                 else
1677                                         DE_FATAL("Unknown permanence.");
1678
1679                                 VK_CHECK(vkd.queueWaitIdle(queue));
1680                         }
1681                 }
1682
1683                 return tcu::TestStatus::pass("Pass");
1684         }
1685 #else
1686         DE_UNREF(context);
1687         DE_UNREF(config);
1688         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1689 #endif
1690 }
1691
1692 tcu::TestStatus testSemaphoreFdDup2 (Context&                                   context,
1693                                                                          const SemaphoreTestConfig      config)
1694 {
1695 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1696         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1697         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1698         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1699         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1700         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1701         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1702
1703         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1704
1705         {
1706                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1707                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1708                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1709                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1710                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1711
1712                 TestLog&                                                        log                     = context.getTestContext().getLog();
1713                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1714                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1715
1716                 {
1717                         NativeHandle            fd, secondFd;
1718
1719                         if (transference == TRANSFERENCE_COPY)
1720                         {
1721                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1722                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1723                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1724                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1725                         }
1726                         else
1727                         {
1728                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1729                                 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1730                         }
1731
1732                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
1733
1734                         if (newFd < 0)
1735                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1736
1737                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1738
1739                         {
1740                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1741
1742                                 if (transference == TRANSFERENCE_COPY)
1743                                         submitEmptyWait(vkd, queue, *semaphoreC);
1744                                 else if (transference == TRANSFERENCE_REFERENCE)
1745                                 {
1746                                         submitEmptySignal(vkd, queue, *semaphoreA);
1747                                         submitEmptyWait(vkd, queue, *semaphoreC);
1748                                 }
1749                                 else
1750                                         DE_FATAL("Unknown permanence.");
1751
1752                                 VK_CHECK(vkd.queueWaitIdle(queue));
1753                         }
1754                 }
1755
1756                 return tcu::TestStatus::pass("Pass");
1757         }
1758 #else
1759         DE_UNREF(context);
1760         DE_UNREF(config);
1761         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1762 #endif
1763 }
1764
1765 tcu::TestStatus testSemaphoreFdDup3 (Context&                                   context,
1766                                                                          const SemaphoreTestConfig      config)
1767 {
1768 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1769         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1770         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1771         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1772         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1773         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1774         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1775
1776         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1777
1778         {
1779                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1780                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1781                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1782                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1783
1784                 TestLog&                                                        log                     = context.getTestContext().getLog();
1785                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1786                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1787
1788                 {
1789                         NativeHandle                                            fd, secondFd;
1790
1791                         if (transference == TRANSFERENCE_COPY)
1792                         {
1793                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1794                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1795                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1796                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1797                         }
1798                         else
1799                         {
1800                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1801                                 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1802                         }
1803
1804                         const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1805                         const int                                                       newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
1806
1807                         if (newFd < 0)
1808                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1809
1810                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1811
1812                         {
1813                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1814
1815                                 if (transference == TRANSFERENCE_COPY)
1816                                         submitEmptyWait(vkd, queue, *semaphoreC);
1817                                 else if (transference == TRANSFERENCE_REFERENCE)
1818                                 {
1819                                         submitEmptySignal(vkd, queue, *semaphoreA);
1820                                         submitEmptyWait(vkd, queue, *semaphoreC);
1821                                 }
1822                                 else
1823                                         DE_FATAL("Unknown permanence.");
1824
1825                                 VK_CHECK(vkd.queueWaitIdle(queue));
1826                         }
1827                 }
1828
1829                 return tcu::TestStatus::pass("Pass");
1830         }
1831 #else
1832         DE_UNREF(context);
1833         DE_UNREF(config);
1834         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1835 #endif
1836 }
1837
1838 tcu::TestStatus testSemaphoreFdSendOverSocket (Context&                                         context,
1839                                                                                            const SemaphoreTestConfig    config)
1840 {
1841 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1842         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1843         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1844         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1845         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1846         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1847         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1848
1849         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1850
1851         {
1852                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1853                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1854                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1855                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1856
1857                 TestLog&                                                        log                     = context.getTestContext().getLog();
1858                 const vk::Unique<vk::VkSemaphore>       semaphore       (createExportableSemaphore(vkd, *device, config.externalType));
1859                 NativeHandle                                            fd;
1860
1861                 if (transference == TRANSFERENCE_COPY)
1862                 {
1863                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1864                         if (fd.getFd() == -1)
1865                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1866                 }
1867                 else
1868                         getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1869
1870                 {
1871                         int sv[2];
1872
1873                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1874                         {
1875                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1876                                 TCU_FAIL("Failed to create socket pair");
1877                         }
1878
1879                         {
1880                                 const NativeHandle      srcSocket       (sv[0]);
1881                                 const NativeHandle      dstSocket       (sv[1]);
1882                                 std::string                     sendData        ("deqp");
1883
1884                                 // Send FD
1885                                 {
1886                                         const int                       fdRaw   (fd.getFd());
1887                                         msghdr                          msg;
1888                                         cmsghdr*                        cmsg;
1889                                         char                            buffer[CMSG_SPACE(sizeof(int))];
1890                                         iovec                           iov             = { &sendData[0], sendData.length()};
1891
1892                                         deMemset(&msg, 0, sizeof(msg));
1893
1894                                         msg.msg_control         = buffer;
1895                                         msg.msg_controllen      = sizeof(buffer);
1896                                         msg.msg_iovlen          = 1;
1897                                         msg.msg_iov                     = &iov;
1898
1899                                         cmsg                            = CMSG_FIRSTHDR(&msg);
1900                                         cmsg->cmsg_level        = SOL_SOCKET;
1901                                         cmsg->cmsg_type         = SCM_RIGHTS;
1902                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
1903
1904                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1905                                         msg.msg_controllen = cmsg->cmsg_len;
1906
1907                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1908                                         {
1909                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1910                                                 TCU_FAIL("Failed to send fd over socket");
1911                                         }
1912                                 }
1913
1914                                 // Recv FD
1915                                 {
1916                                         msghdr                  msg;
1917                                         char                    buffer[CMSG_SPACE(sizeof(int))];
1918                                         std::string             recvData        (4, '\0');
1919                                         iovec                   iov                     = { &recvData[0], recvData.length() };
1920
1921                                         deMemset(&msg, 0, sizeof(msg));
1922
1923                                         msg.msg_control         = buffer;
1924                                         msg.msg_controllen      = sizeof(buffer);
1925                                         msg.msg_iovlen          = 1;
1926                                         msg.msg_iov                     = &iov;
1927
1928                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1929
1930                                         if (bytes < 0)
1931                                         {
1932                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1933                                                 TCU_FAIL("Failed to recv fd over socket");
1934
1935                                         }
1936                                         else if (bytes != (ssize_t)sendData.length())
1937                                         {
1938                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1939                                         }
1940                                         else
1941                                         {
1942                                                 const vk::VkSemaphoreImportFlags        flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1943                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
1944                                                 int                                                                     newFd_;
1945                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1946                                                 NativeHandle                                            newFd   (newFd_);
1947
1948                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1949                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1950                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1951                                                 TCU_CHECK(recvData == sendData);
1952                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1953
1954                                                 {
1955                                                         const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1956
1957                                                         if (transference == TRANSFERENCE_COPY)
1958                                                                 submitEmptyWait(vkd, queue, *newSemaphore);
1959                                                         else if (transference == TRANSFERENCE_REFERENCE)
1960                                                         {
1961                                                                 submitEmptySignal(vkd, queue, *newSemaphore);
1962                                                                 submitEmptyWait(vkd, queue, *newSemaphore);
1963                                                         }
1964                                                         else
1965                                                                 DE_FATAL("Unknown permanence.");
1966
1967                                                         VK_CHECK(vkd.queueWaitIdle(queue));
1968                                                 }
1969                                         }
1970                                 }
1971                         }
1972                 }
1973         }
1974
1975         return tcu::TestStatus::pass("Pass");
1976 #else
1977         DE_UNREF(context);
1978         DE_UNREF(config);
1979         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1980 #endif
1981 }
1982
1983 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1984 {
1985         const CustomInstance                                                    instance        (createTestInstance(context, 0u, 0u, externalType));
1986         const vk::InstanceDriver&                                               vki                     (instance.getDriver());
1987         const vk::VkPhysicalDevice                                              device          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1988
1989         TestLog&                                                                                log                     = context.getTestContext().getLog();
1990
1991         const vk::VkPhysicalDeviceExternalFenceInfo             info            =
1992         {
1993                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1994                 DE_NULL,
1995                 externalType
1996         };
1997         vk::VkExternalFenceProperties                                   properties      =
1998         {
1999                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
2000                 DE_NULL,
2001                 0u,
2002                 0u,
2003                 0u
2004         };
2005
2006         vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2007         log << TestLog::Message << properties << TestLog::EndMessage;
2008
2009         TCU_CHECK(properties.pNext == DE_NULL);
2010         TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2011
2012         return tcu::TestStatus::pass("Pass");
2013 }
2014
2015 struct FenceTestConfig
2016 {
2017                                                                                                 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits  externalType_,
2018                                                                                                                                  Permanence                                                                     permanence_)
2019                 : externalType          (externalType_)
2020                 , permanence            (permanence_)
2021         {
2022         }
2023
2024         vk::VkExternalFenceHandleTypeFlagBits   externalType;
2025         Permanence                                                              permanence;
2026 };
2027
2028 tcu::TestStatus testFenceWin32Create (Context&                          context,
2029                                                                           const FenceTestConfig config)
2030 {
2031 #if (DE_OS == DE_OS_WIN32)
2032         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2033         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2034         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2035         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2036         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2037         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2038
2039         checkFenceSupport(vki, physicalDevice, config.externalType);
2040
2041         {
2042                 const vk::Unique<vk::VkDevice>                          device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2043                 const vk::DeviceDriver                                          vkd                             (vkp, instance, *device);
2044                 const vk::VkQueue                                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
2045                 const vk::VkExportFenceWin32HandleInfoKHR       win32ExportInfo =
2046                 {
2047                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2048                         DE_NULL,
2049
2050                         (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2051                         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2052                         (vk::pt::Win32LPCWSTR)DE_NULL
2053                 };
2054                 const vk::VkExportFenceCreateInfo                       exportCreateInfo=
2055                 {
2056                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2057                         &win32ExportInfo,
2058                         (vk::VkExternalFenceHandleTypeFlags)config.externalType
2059                 };
2060                 const vk::VkFenceCreateInfo                                     createInfo              =
2061                 {
2062                         vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2063                         &exportCreateInfo,
2064                         0u
2065                 };
2066                 const vk::Unique<vk::VkFence>                           fence                   (vk::createFence(vkd, *device, &createInfo));
2067
2068                 if (transference == TRANSFERENCE_COPY)
2069                         submitEmptySignal(vkd, queue, *fence);
2070
2071                 NativeHandle                                                            handleA;
2072                 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2073
2074                 {
2075                         const vk::VkFenceImportFlags                    flags                   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2076                         const vk::Unique<vk::VkFence>                   fenceA                  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2077
2078                         if (transference == TRANSFERENCE_COPY)
2079                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2080                         else if (transference == TRANSFERENCE_REFERENCE)
2081                         {
2082                                 submitEmptySignal(vkd, queue, *fence);
2083                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2084                         }
2085                         else
2086                                 DE_FATAL("Unknown transference.");
2087
2088                         VK_CHECK(vkd.queueWaitIdle(queue));
2089                 }
2090
2091                 return tcu::TestStatus::pass("Pass");
2092         }
2093 #else
2094         DE_UNREF(context);
2095         DE_UNREF(config);
2096         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2097 #endif
2098 }
2099
2100 tcu::TestStatus testFenceImportTwice (Context&                          context,
2101                                                                           const FenceTestConfig config)
2102 {
2103         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2104         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2105         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2106         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2107         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2108         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2109
2110         checkFenceSupport(vki, physicalDevice, config.externalType);
2111
2112         {
2113                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2114                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2115                 vk::SimpleAllocator                             alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2116                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2117                 const vk::Unique<vk::VkFence>   fence           (createExportableFence(vkd, *device, config.externalType));
2118                 NativeHandle                                    handleA;
2119
2120                 if (transference == TRANSFERENCE_COPY)
2121                 {
2122                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2123                         if (handleA.getFd() == -1)
2124                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2125                 }
2126                 else
2127                         getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2128
2129                 {
2130                         NativeHandle                                    handleB (handleA);
2131                         const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2132                         const vk::Unique<vk::VkFence>   fenceA  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2133                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2134
2135                         if (transference == TRANSFERENCE_COPY)
2136                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2137                         else if (transference == TRANSFERENCE_REFERENCE)
2138                         {
2139                                 submitEmptySignal(vkd, queue, *fenceA);
2140                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2141                         }
2142                         else
2143                                 DE_FATAL("Unknown transference.");
2144
2145                         VK_CHECK(vkd.queueWaitIdle(queue));
2146                 }
2147
2148                 return tcu::TestStatus::pass("Pass");
2149         }
2150 }
2151
2152 tcu::TestStatus testFenceImportReimport (Context&                               context,
2153                                                                                  const FenceTestConfig  config)
2154 {
2155         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2156         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2157         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2158         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2159         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2160         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2161
2162         checkFenceSupport(vki, physicalDevice, config.externalType);
2163
2164         {
2165                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2166                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2167                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2168                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2169
2170                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2171                 NativeHandle                                    handleA;
2172
2173                 if (transference == TRANSFERENCE_COPY)
2174                 {
2175                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2176                         if (handleA.getFd() == -1)
2177                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2178                 }
2179                 else
2180                         getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2181
2182                 NativeHandle                                    handleB (handleA);
2183                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2184                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2185
2186                 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2187
2188                 if (transference == TRANSFERENCE_COPY)
2189                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2190                 else if (transference == TRANSFERENCE_REFERENCE)
2191                 {
2192                         submitEmptySignal(vkd, queue, *fenceA);
2193                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2194                 }
2195                 else
2196                         DE_FATAL("Unknown transference.");
2197
2198                 VK_CHECK(vkd.queueWaitIdle(queue));
2199
2200                 return tcu::TestStatus::pass("Pass");
2201         }
2202 }
2203
2204 tcu::TestStatus testFenceSignalExportImportWait (Context&                               context,
2205                                                                                                  const FenceTestConfig  config)
2206 {
2207         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2208         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2209         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2210         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2211         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2212
2213         checkFenceSupport(vki, physicalDevice, config.externalType);
2214
2215         {
2216                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2217                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2218                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2219                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2220                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2221
2222                 {
2223                         NativeHandle    handle;
2224
2225                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2226                         if (handle.getFd() == -1)
2227                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2228
2229                         {
2230                                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2231                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2232                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2233
2234                                 VK_CHECK(vkd.queueWaitIdle(queue));
2235                         }
2236                 }
2237
2238                 return tcu::TestStatus::pass("Pass");
2239         }
2240 }
2241
2242 tcu::TestStatus testFenceImportSyncFdSignaled (Context&                                 context,
2243                                                                                            const FenceTestConfig        config)
2244 {
2245         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2246         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2247         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2248         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2249         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2250         const vk::VkFenceImportFlags            flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2251
2252         checkFenceSupport(vki, physicalDevice, config.externalType);
2253
2254         {
2255                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2256                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2257                 NativeHandle                                    handle  = -1;
2258                 const vk::Unique<vk::VkFence>   fence   (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2259
2260                 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2261                         return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2262
2263                 return tcu::TestStatus::pass("Pass");
2264         }
2265 }
2266
2267 tcu::TestStatus testFenceExportSignalImportWait (Context&                               context,
2268                                                                                                  const FenceTestConfig  config)
2269 {
2270         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2271         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2272         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2273         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2274         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2275         const vk::VkFenceImportFlags            flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2276
2277         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2278         checkFenceSupport(vki, physicalDevice, config.externalType);
2279
2280         {
2281                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2282                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2283                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2284
2285                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2286                 NativeHandle                                    handle;
2287
2288                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2289
2290                 submitEmptySignal(vkd, queue, *fenceA);
2291                 {
2292                         {
2293                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2294
2295                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2296                                 VK_CHECK(vkd.queueWaitIdle(queue));
2297                         }
2298                 }
2299
2300                 return tcu::TestStatus::pass("Pass");
2301         }
2302 }
2303
2304 tcu::TestStatus testFenceExportImportSignalWait (Context&                               context,
2305                                                                                                  const FenceTestConfig  config)
2306 {
2307         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2308         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2309         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2310         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2311         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2312
2313         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2314         checkFenceSupport(vki, physicalDevice, config.externalType);
2315
2316         {
2317                 const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2318                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2319                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2320                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2321
2322                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2323                 NativeHandle                                    handle;
2324
2325                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2326
2327                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2328
2329                 submitEmptySignal(vkd, queue, *fenceA);
2330                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2331
2332                 VK_CHECK(vkd.queueWaitIdle(queue));
2333
2334                 return tcu::TestStatus::pass("Pass");
2335         }
2336 }
2337
2338 tcu::TestStatus testFenceSignalImport (Context&                                 context,
2339                                                                            const FenceTestConfig        config)
2340 {
2341         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2342         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2343         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2344         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2345         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2346         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2347
2348         checkFenceSupport(vki, physicalDevice, config.externalType);
2349
2350         {
2351                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2352                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2353                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2354                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2355                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2356
2357                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2358                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2359                 NativeHandle                                    handle;
2360
2361                 submitEmptySignal(vkd, queue, *fenceB);
2362                 VK_CHECK(vkd.queueWaitIdle(queue));
2363
2364                 if (transference == TRANSFERENCE_COPY)
2365                 {
2366                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2367                         if (handle.getFd() == -1)
2368                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2369                 }
2370                 else
2371                         getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2372
2373                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2374
2375                 if (transference == TRANSFERENCE_COPY)
2376                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2377                 else if (transference == TRANSFERENCE_REFERENCE)
2378                 {
2379                         submitEmptySignal(vkd, queue, *fenceA);
2380                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2381                 }
2382                 else
2383                         DE_FATAL("Unknown transference.");
2384
2385                 VK_CHECK(vkd.queueWaitIdle(queue));
2386
2387                 return tcu::TestStatus::pass("Pass");
2388         }
2389 }
2390
2391 tcu::TestStatus testFenceReset (Context&                                context,
2392                                                                 const FenceTestConfig   config)
2393 {
2394         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2395         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2396         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2397         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2398         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2399         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2400
2401         checkFenceSupport(vki, physicalDevice, config.externalType);
2402
2403         {
2404                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2405                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2406                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2407                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2408                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2409
2410                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2411                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2412                 const vk::Unique<vk::VkFence>   fenceC  (createFence(vkd, *device));
2413                 NativeHandle                                    handle;
2414
2415                 submitEmptySignal(vkd, queue, *fenceB);
2416                 VK_CHECK(vkd.queueWaitIdle(queue));
2417
2418                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2419                 if (handle.getFd() == -1)
2420                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2421
2422                 NativeHandle                                    handleB (handle);
2423                 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2424                 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2425
2426                 VK_CHECK(vkd.queueWaitIdle(queue));
2427                 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2428
2429                 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2430                 {
2431                         // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2432                         // or fenceB should be separate copy of the payload and not affect fenceC
2433                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2434
2435                         // vkResetFences() should have restored fenceBs prior state and should be now reset
2436                         // or fenceB should have it's separate payload
2437                         submitEmptySignal(vkd, queue, *fenceB);
2438                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2439                 }
2440                 else if (config.permanence == PERMANENCE_PERMANENT)
2441                 {
2442                         DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2443
2444                         // Reset fences should have reset all of the fences
2445                         submitEmptySignal(vkd, queue, *fenceC);
2446
2447                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2448                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2449                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2450                 }
2451                 else
2452                         DE_FATAL("Unknown permanence");
2453
2454                 VK_CHECK(vkd.queueWaitIdle(queue));
2455
2456                 return tcu::TestStatus::pass("Pass");
2457         }
2458 }
2459
2460 tcu::TestStatus testFenceSignalWaitImport (Context&                                     context,
2461                                                                                    const FenceTestConfig        config)
2462 {
2463         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2464         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2465         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2466         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2467         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2468
2469         checkFenceSupport(vki, physicalDevice, config.externalType);
2470
2471         {
2472                 const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2473                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2474                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2475                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2476
2477                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2478                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2479                 NativeHandle                                    handle;
2480
2481                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2482
2483                 submitEmptySignal(vkd, queue, *fenceB);
2484                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2485
2486                 VK_CHECK(vkd.queueWaitIdle(queue));
2487
2488                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2489
2490                 submitEmptySignal(vkd, queue, *fenceA);
2491                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2492
2493                 VK_CHECK(vkd.queueWaitIdle(queue));
2494
2495                 return tcu::TestStatus::pass("Pass");
2496         }
2497 }
2498
2499 tcu::TestStatus testFenceMultipleExports (Context&                              context,
2500                                                                                   const FenceTestConfig config)
2501 {
2502         const size_t                                            exportCount                     = 1024;
2503         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2504         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2505         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2506         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2507         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2508         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2509
2510         checkFenceSupport(vki, physicalDevice, config.externalType);
2511
2512         {
2513                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2514                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2515                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2516                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2517                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
2518
2519                 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2520                 {
2521                         NativeHandle handle;
2522
2523                         // Need to touch watchdog due to how long one iteration takes
2524                         context.getTestContext().touchWatchdog();
2525
2526                         if (transference == TRANSFERENCE_COPY)
2527                         {
2528                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2529                                 if (handle.getFd() == -1)
2530                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2531                         }
2532                         else
2533                                 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2534                 }
2535
2536                 submitEmptySignal(vkd, queue, *fence);
2537                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2538
2539                 VK_CHECK(vkd.queueWaitIdle(queue));
2540         }
2541
2542         return tcu::TestStatus::pass("Pass");
2543 }
2544
2545 tcu::TestStatus testFenceMultipleImports (Context&                              context,
2546                                                                                   const FenceTestConfig config)
2547 {
2548         const size_t                                            importCount                     = 4 * 1024;
2549         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2550         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2551         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2552         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2553         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2554         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2555
2556         checkFenceSupport(vki, physicalDevice, config.externalType);
2557
2558         {
2559                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2560                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2561                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2562                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2563                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2564                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2565                 NativeHandle                                    handleA;
2566
2567                 if (transference == TRANSFERENCE_COPY)
2568                 {
2569                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2570                         if (handleA.getFd() == -1)
2571                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2572                 }
2573                 else
2574                         getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2575
2576                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2577                 {
2578                         NativeHandle                                    handleB         (handleA);
2579                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2580                 }
2581
2582                 if (transference == TRANSFERENCE_COPY)
2583                 {
2584                         importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2585                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2586                 }
2587                 else if (transference == TRANSFERENCE_REFERENCE)
2588                 {
2589                         submitEmptySignal(vkd, queue, *fenceA);
2590                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2591                 }
2592                 else
2593                         DE_FATAL("Unknown transference.");
2594
2595                 VK_CHECK(vkd.queueWaitIdle(queue));
2596         }
2597
2598         return tcu::TestStatus::pass("Pass");
2599 }
2600
2601 tcu::TestStatus testFenceTransference (Context&                                 context,
2602                                                                            const FenceTestConfig        config)
2603 {
2604         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2605         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2606         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2607         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2608         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2609         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2610
2611         checkFenceSupport(vki, physicalDevice, config.externalType);
2612
2613         {
2614                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2615                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2616                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2617                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2618                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2619
2620                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2621                 NativeHandle                                    handle;
2622
2623                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2624                 if (handle.getFd() == -1)
2625                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2626
2627                 {
2628                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2629
2630                         if (config.permanence == PERMANENCE_PERMANENT)
2631                         {
2632                                 if (transference == TRANSFERENCE_COPY)
2633                                 {
2634                                         submitEmptySignal(vkd, queue, *fenceA);
2635                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2636                                         VK_CHECK(vkd.queueWaitIdle(queue));
2637
2638                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2639                                         submitEmptySignal(vkd, queue, *fenceB);
2640
2641                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2642                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2643                                         VK_CHECK(vkd.queueWaitIdle(queue));
2644                                 }
2645                                 else if (transference== TRANSFERENCE_REFERENCE)
2646                                 {
2647                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2648                                         VK_CHECK(vkd.queueWaitIdle(queue));
2649
2650                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2651                                         submitEmptySignal(vkd, queue, *fenceA);
2652                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2653
2654                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2655                                         submitEmptySignal(vkd, queue, *fenceB);
2656                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2657                                         VK_CHECK(vkd.queueWaitIdle(queue));
2658                                 }
2659                                 else
2660                                         DE_FATAL("Unknown transference.");
2661                         }
2662                         else if (config.permanence == PERMANENCE_TEMPORARY)
2663                         {
2664                                 if (transference == TRANSFERENCE_COPY)
2665                                 {
2666                                         submitEmptySignal(vkd, queue, *fenceA);
2667                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2668                                         VK_CHECK(vkd.queueWaitIdle(queue));
2669
2670                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2671                                         submitEmptySignal(vkd, queue, *fenceB);
2672
2673                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2674                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2675                                         VK_CHECK(vkd.queueWaitIdle(queue));
2676                                 }
2677                                 else if (transference == TRANSFERENCE_REFERENCE)
2678                                 {
2679                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2680                                         VK_CHECK(vkd.queueWaitIdle(queue));
2681
2682                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2683                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2684                                         submitEmptySignal(vkd, queue, *fenceA);
2685                                         submitEmptySignal(vkd, queue, *fenceB);
2686
2687                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2688                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2689                                         VK_CHECK(vkd.queueWaitIdle(queue));
2690                                 }
2691                                 else
2692                                         DE_FATAL("Unknown transference.");
2693                         }
2694                         else
2695                                 DE_FATAL("Unknown permanence.");
2696                 }
2697
2698                 return tcu::TestStatus::pass("Pass");
2699         }
2700 }
2701
2702 tcu::TestStatus testFenceFdDup (Context&                                context,
2703                                                                 const FenceTestConfig   config)
2704 {
2705 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2706         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2707         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2708         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2709         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2710         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2711         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2712
2713         checkFenceSupport(vki, physicalDevice, config.externalType);
2714
2715         {
2716                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2717                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2718                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2719                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2720                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2721
2722                 TestLog&                                                log             = context.getTestContext().getLog();
2723                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2724
2725                 {
2726                         NativeHandle            fd;
2727
2728                         if (transference == TRANSFERENCE_COPY)
2729                         {
2730                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2731                                 if (fd.getFd() == -1)
2732                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2733                         }
2734                         else
2735                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2736
2737                         NativeHandle            newFd   (dup(fd.getFd()));
2738
2739                         if (newFd.getFd() < 0)
2740                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2741
2742                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2743
2744                         {
2745                                 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2746
2747                                 if (transference == TRANSFERENCE_COPY)
2748                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2749                                 else if (transference == TRANSFERENCE_REFERENCE)
2750                                 {
2751                                         submitEmptySignal(vkd, queue, *fenceA);
2752                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2753                                 }
2754                                 else
2755                                         DE_FATAL("Unknown permanence.");
2756
2757                                 VK_CHECK(vkd.queueWaitIdle(queue));
2758                         }
2759                 }
2760
2761                 return tcu::TestStatus::pass("Pass");
2762         }
2763 #else
2764         DE_UNREF(context);
2765         DE_UNREF(config);
2766         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2767 #endif
2768 }
2769
2770 tcu::TestStatus testFenceFdDup2 (Context&                               context,
2771                                                                  const FenceTestConfig  config)
2772 {
2773 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2774         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2775         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2776         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2777         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2778         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2779         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2780
2781         checkFenceSupport(vki, physicalDevice, config.externalType);
2782
2783         {
2784                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2785                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2786                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2787                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2788                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2789
2790                 TestLog&                                                log             = context.getTestContext().getLog();
2791                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2792                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2793
2794                 {
2795                         NativeHandle            fd, secondFd;
2796
2797                         if (transference == TRANSFERENCE_COPY)
2798                         {
2799                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2800                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2801                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2802                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2803                         }
2804                         else
2805                         {
2806                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2807                                 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2808                         }
2809
2810                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
2811
2812                         if (newFd < 0)
2813                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2814
2815                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2816
2817                         {
2818                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2819
2820                                 if (transference == TRANSFERENCE_COPY)
2821                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2822                                 else if (transference == TRANSFERENCE_REFERENCE)
2823                                 {
2824                                         submitEmptySignal(vkd, queue, *fenceA);
2825                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2826                                 }
2827                                 else
2828                                         DE_FATAL("Unknown permanence.");
2829
2830                                 VK_CHECK(vkd.queueWaitIdle(queue));
2831                         }
2832                 }
2833
2834                 return tcu::TestStatus::pass("Pass");
2835         }
2836 #else
2837         DE_UNREF(context);
2838         DE_UNREF(config);
2839         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2840 #endif
2841 }
2842
2843 tcu::TestStatus testFenceFdDup3 (Context&                               context,
2844                                                                  const FenceTestConfig  config)
2845 {
2846 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2847         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2848         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2849         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2850         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2851         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2852         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2853
2854         checkFenceSupport(vki, physicalDevice, config.externalType);
2855
2856         {
2857                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2858                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2859                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2860                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2861
2862                 TestLog&                                                log             = context.getTestContext().getLog();
2863                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2864                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2865
2866                 {
2867                         NativeHandle                                    fd, secondFd;
2868
2869                         if (transference == TRANSFERENCE_COPY)
2870                         {
2871                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2872                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2873                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2874                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2875                         }
2876                         else
2877                         {
2878                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2879                                 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2880                         }
2881
2882                         const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2883                         const int                                               newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
2884
2885                         if (newFd < 0)
2886                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2887
2888                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2889
2890                         {
2891                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2892
2893                                 if (transference == TRANSFERENCE_COPY)
2894                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2895                                 else if (transference == TRANSFERENCE_REFERENCE)
2896                                 {
2897                                         submitEmptySignal(vkd, queue, *fenceA);
2898                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2899                                 }
2900                                 else
2901                                         DE_FATAL("Unknown permanence.");
2902
2903                                 VK_CHECK(vkd.queueWaitIdle(queue));
2904                         }
2905                 }
2906
2907                 return tcu::TestStatus::pass("Pass");
2908         }
2909 #else
2910         DE_UNREF(context);
2911         DE_UNREF(config);
2912         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2913 #endif
2914 }
2915
2916 tcu::TestStatus testFenceFdSendOverSocket (Context&                                     context,
2917                                                                                    const FenceTestConfig        config)
2918 {
2919 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2920         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2921         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2922         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2923         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2924         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2925         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2926
2927         checkFenceSupport(vki, physicalDevice, config.externalType);
2928
2929         {
2930                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2931                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2932                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2933                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2934
2935                 TestLog&                                                log             = context.getTestContext().getLog();
2936                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
2937                 NativeHandle                                    fd;
2938
2939                 if (transference == TRANSFERENCE_COPY)
2940                 {
2941                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2942                         if (fd.getFd() == -1)
2943                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2944                 }
2945                 else
2946                         getFenceNative(vkd, *device, *fence, config.externalType, fd);
2947
2948                 {
2949                         int sv[2];
2950
2951                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2952                         {
2953                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2954                                 TCU_FAIL("Failed to create socket pair");
2955                         }
2956
2957                         {
2958                                 const NativeHandle      srcSocket       (sv[0]);
2959                                 const NativeHandle      dstSocket       (sv[1]);
2960                                 std::string                     sendData        ("deqp");
2961
2962                                 // Send FD
2963                                 {
2964                                         const int                       fdRaw   (fd.getFd());
2965                                         msghdr                          msg;
2966                                         cmsghdr*                        cmsg;
2967                                         char                            buffer[CMSG_SPACE(sizeof(int))];
2968                                         iovec                           iov             = { &sendData[0], sendData.length()};
2969
2970                                         deMemset(&msg, 0, sizeof(msg));
2971
2972                                         msg.msg_control         = buffer;
2973                                         msg.msg_controllen      = sizeof(buffer);
2974                                         msg.msg_iovlen          = 1;
2975                                         msg.msg_iov                     = &iov;
2976
2977                                         cmsg                            = CMSG_FIRSTHDR(&msg);
2978                                         cmsg->cmsg_level        = SOL_SOCKET;
2979                                         cmsg->cmsg_type         = SCM_RIGHTS;
2980                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
2981
2982                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2983                                         msg.msg_controllen = cmsg->cmsg_len;
2984
2985                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2986                                         {
2987                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2988                                                 TCU_FAIL("Failed to send fd over socket");
2989                                         }
2990                                 }
2991
2992                                 // Recv FD
2993                                 {
2994                                         msghdr                  msg;
2995                                         char                    buffer[CMSG_SPACE(sizeof(int))];
2996                                         std::string             recvData        (4, '\0');
2997                                         iovec                   iov                     = { &recvData[0], recvData.length() };
2998
2999                                         deMemset(&msg, 0, sizeof(msg));
3000
3001                                         msg.msg_control         = buffer;
3002                                         msg.msg_controllen      = sizeof(buffer);
3003                                         msg.msg_iovlen          = 1;
3004                                         msg.msg_iov                     = &iov;
3005
3006                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3007
3008                                         if (bytes < 0)
3009                                         {
3010                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3011                                                 TCU_FAIL("Failed to recv fd over socket");
3012
3013                                         }
3014                                         else if (bytes != (ssize_t)sendData.length())
3015                                         {
3016                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3017                                         }
3018                                         else
3019                                         {
3020                                                 const vk::VkFenceImportFlags            flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3021                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
3022                                                 int                                                                     newFd_;
3023                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3024                                                 NativeHandle                                            newFd   (newFd_);
3025
3026                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3027                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3028                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3029                                                 TCU_CHECK(recvData == sendData);
3030                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3031
3032                                                 {
3033                                                         const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3034
3035                                                         if (transference == TRANSFERENCE_COPY)
3036                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3037                                                         else if (transference == TRANSFERENCE_REFERENCE)
3038                                                         {
3039                                                                 submitEmptySignal(vkd, queue, *newFence);
3040                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3041                                                         }
3042                                                         else
3043                                                                 DE_FATAL("Unknown permanence.");
3044
3045                                                         VK_CHECK(vkd.queueWaitIdle(queue));
3046                                                 }
3047                                         }
3048                                 }
3049                         }
3050                 }
3051         }
3052
3053         return tcu::TestStatus::pass("Pass");
3054 #else
3055         DE_UNREF(context);
3056         DE_UNREF(config);
3057         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3058 #endif
3059 }
3060
3061 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3062 {
3063         const vk::VkBufferCreateFlags           createFlags[]           =
3064         {
3065                 0u,
3066                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3067                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3068                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3069         };
3070         const vk::VkBufferUsageFlags            usageFlags[]            =
3071         {
3072                 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3073                 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3074                 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3075                 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3076                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3077                 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3078                 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3079                 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3080                 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3081         };
3082         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3083         const CustomInstance                            instance                        (createTestInstance(context, 0u, externalType, 0u));
3084         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3085         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3086         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3087         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3088
3089         // VkDevice is only created if physical device claims to support any of these types.
3090         vk::Move<vk::VkDevice>                          device;
3091         de::MovePtr<vk::DeviceDriver>           vkd;
3092         bool                                                            deviceHasDedicated      = false;
3093
3094         TestLog&                                                        log                                     = context.getTestContext().getLog();
3095
3096         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3097         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3098         {
3099                 const vk::VkBufferViewCreateFlags                               createFlag              = createFlags[createFlagNdx];
3100                 const vk::VkBufferUsageFlags                                    usageFlag               = usageFlags[usageFlagNdx];
3101                 const vk::VkPhysicalDeviceExternalBufferInfo    info                    =
3102                 {
3103                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3104                         DE_NULL,
3105                         createFlag,
3106                         usageFlag,
3107                         externalType
3108                 };
3109                 vk::VkExternalBufferProperties                                  properties              =
3110                 {
3111                         vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3112                         DE_NULL,
3113                         { 0u, 0u, 0u }
3114                 };
3115
3116                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3117                         (deviceFeatures.sparseBinding == VK_FALSE))
3118                         continue;
3119
3120                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3121                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3122                         continue;
3123
3124                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3125                         (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3126                         continue;
3127
3128                 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3129
3130                 log << TestLog::Message << properties << TestLog::EndMessage;
3131
3132                 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3133                 TCU_CHECK(properties.pNext == DE_NULL);
3134                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3135
3136                 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3137                 {
3138                         const bool      requiresDedicated       = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3139
3140                         if (!device || (requiresDedicated && !deviceHasDedicated))
3141                         {
3142                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3143                                 try
3144                                 {
3145                                         device                          = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3146                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3147                                         deviceHasDedicated      = requiresDedicated;
3148                                 }
3149                                 catch (const tcu::NotSupportedError& e)
3150                                 {
3151                                         log << e;
3152                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3153                                 }
3154                         }
3155                 }
3156
3157                 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3158                 {
3159                         DE_ASSERT(!!device);
3160                         DE_ASSERT(vkd);
3161
3162                         if (deviceHasDedicated)
3163                         {
3164                                 const vk::Unique<vk::VkBuffer>                          buffer                                          (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3165                                 const vk::VkMemoryDedicatedRequirements         reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3166                                 const bool                                                                      propertiesRequiresDedicated     = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3167                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
3168
3169                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
3170                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3171                         }
3172                         else
3173                         {
3174                                 // We can't query whether dedicated memory is required or not on per-object basis.
3175                                 // This check should be redundant as the code above tries to create device with
3176                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3177                                 // is required. However, checking again doesn't hurt.
3178                                 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3179                         }
3180                 }
3181         }
3182
3183         return tcu::TestStatus::pass("Pass");
3184 }
3185
3186 struct MemoryTestConfig
3187 {
3188                                                                                                 MemoryTestConfig        (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3189                                                                                                                                          bool                                                                           hostVisible_,
3190                                                                                                                                          bool                                                                           dedicated_)
3191                 : externalType  (externalType_)
3192                 , hostVisible   (hostVisible_)
3193                 , dedicated             (dedicated_)
3194         {
3195         }
3196
3197         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
3198         bool                                                                    hostVisible;
3199         bool                                                                    dedicated;
3200 };
3201
3202 #if (DE_OS == DE_OS_WIN32)
3203 deUint32 chooseWin32MemoryType(deUint32 bits)
3204 {
3205         if (bits == 0)
3206                 TCU_THROW(NotSupportedError, "No compatible memory type found");
3207
3208         return deCtz32(bits);
3209 }
3210 #endif
3211
3212 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3213 {
3214 #if (DE_OS == DE_OS_WIN32)
3215         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
3216         const CustomInstance                                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3217         const vk::InstanceDriver&                                       vki                                     (instance.getDriver());
3218         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3219         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3220         const vk::Unique<vk::VkDevice>                          device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3221         const vk::DeviceDriver                                          vkd                                     (vkp, instance, *device);
3222         const vk::VkBufferUsageFlags                            usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3223         const deUint32                                                          seed                            = 1261033864u;
3224         const vk::VkDeviceSize                                          bufferSize                      = 1024;
3225         const std::vector<deUint8>                                      testData                        (genTestData(seed, (size_t)bufferSize));
3226
3227         const vk::VkPhysicalDeviceMemoryProperties      memoryProps                     = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3228         const deUint32                                                          compatibleMemTypes      = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3229
3230         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3231
3232         // \note Buffer is only allocated to get memory requirements
3233         const vk::Unique<vk::VkBuffer>                          buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3234         const vk::VkMemoryRequirements                          requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3235         const vk::VkExportMemoryWin32HandleInfoKHR      win32Info                               =
3236         {
3237                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3238                 DE_NULL,
3239
3240                 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3241                 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3242                 (vk::pt::Win32LPCWSTR)DE_NULL
3243         };
3244         const vk::VkExportMemoryAllocateInfo            exportInfo                      =
3245         {
3246                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3247                 &win32Info,
3248                 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
3249         };
3250
3251         const deUint32                                                          exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3252         const vk::VkMemoryAllocateInfo                          info                                    =
3253         {
3254                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3255                 &exportInfo,
3256                 requirements.size,
3257                 exportedMemoryTypeIndex
3258         };
3259         const vk::Unique<vk::VkDeviceMemory>            memory                                  (vk::allocateMemory(vkd, *device, &info));
3260         NativeHandle                                                            handleA;
3261
3262         if (config.hostVisible)
3263                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3264
3265         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3266
3267         {
3268                 const vk::Unique<vk::VkDeviceMemory>    memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3269
3270                 if (config.hostVisible)
3271                 {
3272                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3273                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3274
3275                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3276                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testData[0]);
3277
3278                         writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3279                         writeHostMemory(vkd, *device, *memory,  testDataA.size(), &testDataB[0]);
3280
3281                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3282                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testDataB[0]);
3283                 }
3284         }
3285
3286         return tcu::TestStatus::pass("Pass");
3287 #else
3288         DE_UNREF(context);
3289         DE_UNREF(config);
3290         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3291 #endif
3292 }
3293
3294 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3295 {
3296         if (hostVisible)
3297         {
3298                 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3299                 return chooseHostVisibleMemoryType(memoryBits, properties);
3300         }
3301
3302         return chooseMemoryType(memoryBits);
3303 }
3304
3305 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3306 {
3307         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3308         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3309         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3310         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3311         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3312         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3313         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3314         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3315         const deUint32                                                  seed                            = 1261033864u;
3316         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3317         const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
3318
3319         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3320
3321         // \note Buffer is only allocated to get memory requirements
3322         const vk::Unique<vk::VkBuffer>                          buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3323         const vk::VkMemoryRequirements                          requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3324         const deUint32                                                          exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3325         const vk::Unique<vk::VkDeviceMemory>            memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3326         NativeHandle                                                            handleA;
3327
3328         if (config.hostVisible)
3329                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3330
3331         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3332
3333         {
3334                 const vk::Unique<vk::VkBuffer>                  bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3335                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3336                 NativeHandle                                                    handleB (handleA);
3337                 const vk::Unique<vk::VkDeviceMemory>    memoryA (config.dedicated
3338                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3339                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3340                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3341                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3342                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3343
3344                 if (config.hostVisible)
3345                 {
3346                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3347                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3348
3349                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3350                         checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3351
3352                         writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3353                         writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3354
3355                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3356                         checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3357                 }
3358         }
3359
3360         return tcu::TestStatus::pass("Pass");
3361 }
3362
3363 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3364 {
3365         const size_t                                                    count                           = 4 * 1024;
3366         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3367         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3368         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3369         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3370         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3371         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3372         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3373         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3374         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3375
3376         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3377
3378         // \note Buffer is only allocated to get memory requirements
3379         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3380         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3381         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3382         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3383         NativeHandle                                                    handleA;
3384
3385         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3386
3387         for (size_t ndx = 0; ndx < count; ndx++)
3388         {
3389                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3390                 NativeHandle                                                    handleB (handleA);
3391                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3392                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3393                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3394         }
3395
3396         return tcu::TestStatus::pass("Pass");
3397 }
3398
3399 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3400 {
3401         const size_t                                                    count                           = 4 * 1024;
3402         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3403         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3404         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3405         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3406         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3407         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3408         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3409         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3410         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3411
3412         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3413
3414         // \note Buffer is only allocated to get memory requirements
3415         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3416         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3417         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3418         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3419
3420         for (size_t ndx = 0; ndx < count; ndx++)
3421         {
3422                 NativeHandle    handle;
3423                 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3424         }
3425
3426         return tcu::TestStatus::pass("Pass");
3427 }
3428
3429 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3430 {
3431         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3432         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3433         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3434         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3435         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3436         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3437         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3438         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3439         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3440
3441         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3442
3443         // \note Buffer is only allocated to get memory requirements
3444         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3445         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3446         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3447         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3448
3449         vk::VkMemoryFdPropertiesKHR     properties;
3450         NativeHandle                            handle;
3451
3452         getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3453         properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3454         vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3455
3456         switch (config.externalType)
3457         {
3458                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3459                         TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3460                         break;
3461                 default:
3462                         // Invalid external memory type for this test.
3463                         DE_ASSERT(false);
3464                         break;
3465         }
3466
3467         return tcu::TestStatus::pass("Pass");
3468 }
3469
3470 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3471 {
3472 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3473         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3474         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3475         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3476         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3477         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3478
3479         {
3480                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3481                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3482
3483                 TestLog&                                                                log                             = context.getTestContext().getLog();
3484                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3485                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3486                 const deUint32                                                  seed                    = 851493858u;
3487                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3488
3489                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3490
3491                 // \note Buffer is only allocated to get memory requirements
3492                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3493                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3494                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3495                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3496
3497                 if (config.hostVisible)
3498                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3499
3500                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3501                 NativeHandle                                                    newFd                   (dup(fd.getFd()));
3502
3503                 if (newFd.getFd() < 0)
3504                         log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3505
3506                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3507
3508                 {
3509                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3510                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3511                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3512                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3513
3514                         if (config.hostVisible)
3515                         {
3516                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3517
3518                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3519
3520                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3521                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3522                         }
3523                 }
3524
3525                 return tcu::TestStatus::pass("Pass");
3526         }
3527 #else
3528         DE_UNREF(context);
3529         DE_UNREF(config);
3530         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3531 #endif
3532 }
3533
3534 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3535 {
3536 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3537         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3538         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3539         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3540         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3541         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3542
3543         {
3544                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3545                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3546
3547                 TestLog&                                                                log                             = context.getTestContext().getLog();
3548                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3549                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3550                 const deUint32                                                  seed                    = 224466865u;
3551                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3552
3553                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3554
3555                 // \note Buffer is only allocated to get memory requirements
3556                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3557                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3558                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3559                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3560
3561                 if (config.hostVisible)
3562                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3563
3564                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3565                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
3566                 const int                                                               newFd                   (dup2(fd.getFd(), secondFd.getFd()));
3567
3568                 if (newFd < 0)
3569                         log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3570
3571                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3572
3573                 {
3574                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3575                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3576                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3577                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3578
3579                         if (config.hostVisible)
3580                         {
3581                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3582
3583                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3584
3585                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3586                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3587                         }
3588                 }
3589
3590                 return tcu::TestStatus::pass("Pass");
3591         }
3592 #else
3593         DE_UNREF(context);
3594         DE_UNREF(config);
3595         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3596 #endif
3597 }
3598
3599 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3600 {
3601 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3602         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3603         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3604         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3605         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3606         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3607
3608         {
3609                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3610                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3611
3612                 TestLog&                                                                log                             = context.getTestContext().getLog();
3613                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3614                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3615                 const deUint32                                                  seed                    = 2554088961u;
3616                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3617
3618                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3619
3620                 // \note Buffer is only allocated to get memory requirements
3621                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3622                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3623                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3624                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3625
3626                 if (config.hostVisible)
3627                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3628
3629                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3630                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
3631                 const int                                                               newFd                   (dup3(fd.getFd(), secondFd.getFd(), 0));
3632
3633                 if (newFd < 0)
3634                         log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3635
3636                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3637
3638                 {
3639                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3640                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3641                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3642                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3643
3644                         if (config.hostVisible)
3645                         {
3646                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3647
3648                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3649
3650                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3651                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3652                         }
3653                 }
3654
3655                 return tcu::TestStatus::pass("Pass");
3656         }
3657 #else
3658         DE_UNREF(context);
3659         DE_UNREF(config);
3660         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3661 #endif
3662 }
3663
3664 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3665 {
3666 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3667         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
3668         const CustomInstance                                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3669         const vk::InstanceDriver&                                       vki                                     (instance.getDriver());
3670         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3671         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3672
3673         {
3674                 const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3675                 const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3676
3677                 TestLog&                                                                log                                     = context.getTestContext().getLog();
3678                 const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3679                 const vk::VkDeviceSize                                  bufferSize                      = 1024;
3680                 const deUint32                                                  seed                            = 3403586456u;
3681                 const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
3682
3683                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3684
3685                 // \note Buffer is only allocated to get memory requirements
3686                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3687                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3688                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3689                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3690
3691                 if (config.hostVisible)
3692                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3693
3694                 const NativeHandle                                              fd                                      (getMemoryFd(vkd, *device, *memory, config.externalType));
3695
3696                 {
3697                         int sv[2];
3698
3699                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3700                         {
3701                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3702                                 TCU_FAIL("Failed to create socket pair");
3703                         }
3704
3705                         {
3706                                 const NativeHandle      srcSocket       (sv[0]);
3707                                 const NativeHandle      dstSocket       (sv[1]);
3708                                 std::string                     sendData        ("deqp");
3709
3710                                 // Send FD
3711                                 {
3712                                         const int                       fdRaw   (fd.getFd());
3713                                         msghdr                          msg;
3714                                         cmsghdr*                        cmsg;
3715                                         char                            tmpBuffer[CMSG_SPACE(sizeof(int))];
3716                                         iovec                           iov             = { &sendData[0], sendData.length()};
3717
3718                                         deMemset(&msg, 0, sizeof(msg));
3719
3720                                         msg.msg_control         = tmpBuffer;
3721                                         msg.msg_controllen      = sizeof(tmpBuffer);
3722                                         msg.msg_iovlen          = 1;
3723                                         msg.msg_iov                     = &iov;
3724
3725                                         cmsg                            = CMSG_FIRSTHDR(&msg);
3726                                         cmsg->cmsg_level        = SOL_SOCKET;
3727                                         cmsg->cmsg_type         = SCM_RIGHTS;
3728                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
3729
3730                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3731                                         msg.msg_controllen = cmsg->cmsg_len;
3732
3733                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3734                                         {
3735                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3736                                                 TCU_FAIL("Failed to send fd over socket");
3737                                         }
3738                                 }
3739
3740                                 // Recv FD
3741                                 {
3742                                         msghdr                  msg;
3743                                         char                    tmpBuffer[CMSG_SPACE(sizeof(int))];
3744                                         std::string             recvData        (4, '\0');
3745                                         iovec                   iov                     = { &recvData[0], recvData.length() };
3746
3747                                         deMemset(&msg, 0, sizeof(msg));
3748
3749                                         msg.msg_control         = tmpBuffer;
3750                                         msg.msg_controllen      = sizeof(tmpBuffer);
3751                                         msg.msg_iovlen          = 1;
3752                                         msg.msg_iov                     = &iov;
3753
3754                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3755
3756                                         if (bytes < 0)
3757                                         {
3758                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3759                                                 TCU_FAIL("Failed to recv fd over socket");
3760
3761                                         }
3762                                         else if (bytes != (ssize_t)sendData.length())
3763                                         {
3764                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3765                                         }
3766                                         else
3767                                         {
3768                                                 const cmsghdr* const    cmsg    = CMSG_FIRSTHDR(&msg);
3769                                                 int                                             newFd_;
3770                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3771                                                 NativeHandle                    newFd   (newFd_);
3772
3773                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3774                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3775                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3776                                                 TCU_CHECK(recvData == sendData);
3777                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3778
3779                                                 {
3780                                                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3781                                                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3782                                                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3783                                                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3784
3785                                                         if (config.hostVisible)
3786                                                         {
3787                                                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3788
3789                                                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3790
3791                                                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3792                                                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3793                                                         }
3794                                                 }
3795                                         }
3796                                 }
3797                         }
3798                 }
3799         }
3800
3801         return tcu::TestStatus::pass("Pass");
3802 #else
3803         DE_UNREF(context);
3804         DE_UNREF(config);
3805         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3806 #endif
3807 }
3808
3809 struct BufferTestConfig
3810 {
3811                                                                                         BufferTestConfig        (vk::VkExternalMemoryHandleTypeFlagBits         externalType_,
3812                                                                                                                                  bool                                                                           dedicated_)
3813                 : externalType  (externalType_)
3814                 , dedicated             (dedicated_)
3815         {
3816         }
3817
3818         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
3819         bool                                                                    dedicated;
3820 };
3821
3822 tcu::TestStatus testBufferBindExportImportBind (Context&                                context,
3823                                                                                                 const BufferTestConfig  config)
3824 {
3825         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3826         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3827         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3828         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3829         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3830         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3831         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3832         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3833         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3834
3835         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3836
3837         // \note Buffer is only allocated to get memory requirements
3838         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3839         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3840         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3841         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3842         NativeHandle                                                    handle;
3843
3844         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3845
3846         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3847
3848         {
3849                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3850                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3851                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3852                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3853
3854                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3855         }
3856
3857         return tcu::TestStatus::pass("Pass");
3858 }
3859
3860 tcu::TestStatus testBufferExportBindImportBind (Context&                                context,
3861                                                                                                 const BufferTestConfig  config)
3862 {
3863         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3864         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3865         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3866         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3867         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3868         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3869         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3870         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3871         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3872
3873         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3874
3875         // \note Buffer is only allocated to get memory requirements
3876         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3877         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3878         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3879         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3880         NativeHandle                                                    handle;
3881
3882         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3883         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3884
3885         {
3886                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3887                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3888                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3889                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3890
3891                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3892         }
3893
3894         return tcu::TestStatus::pass("Pass");
3895 }
3896
3897 tcu::TestStatus testBufferExportImportBindBind (Context&                                context,
3898                                                                                                 const BufferTestConfig  config)
3899 {
3900         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3901         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3902         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3903         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3904         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3905         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3906         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3907         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3908         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3909
3910         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3911
3912         // \note Buffer is only allocated to get memory requirements
3913         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3914         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3915         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3916         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3917         NativeHandle                                                    handle;
3918
3919         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3920
3921         {
3922                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3923                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3924                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3925                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3926
3927                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3928                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3929         }
3930
3931         return tcu::TestStatus::pass("Pass");
3932 }
3933
3934 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3935 {
3936         const vk::VkImageCreateFlags            createFlags[]           =
3937         {
3938                 0u,
3939                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3940                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3941                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3942                 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3943                 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3944         };
3945         const vk::VkImageUsageFlags                     usageFlags[]            =
3946         {
3947                 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3948                 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3949                 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3950                 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3951                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3952                 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3953                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3954                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3955                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3956                 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3957         };
3958         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3959         const CustomInstance                            instance                        (createTestInstance(context, 0u, externalType, 0u));
3960         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3961         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3962         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3963         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3964
3965         // VkDevice is only created if physical device claims to support any of these types.
3966         vk::Move<vk::VkDevice>                          device;
3967         de::MovePtr<vk::DeviceDriver>           vkd;
3968         bool                                                            deviceHasDedicated      = false;
3969
3970         TestLog&                                                        log                                     = context.getTestContext().getLog();
3971
3972         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3973         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3974         {
3975                 const vk::VkImageViewCreateFlags                                                createFlag              = createFlags[createFlagNdx];
3976                 const vk::VkImageUsageFlags                                                             usageFlag               = usageFlags[usageFlagNdx];
3977                 const vk::VkFormat                                                                              format                  =
3978                                 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3979                 const vk::VkImageType                                                                   type                    = vk::VK_IMAGE_TYPE_2D;
3980                 const vk::VkImageTiling                                                                 tiling                  = vk::VK_IMAGE_TILING_OPTIMAL;
3981                 const vk::VkPhysicalDeviceExternalImageFormatInfo               externalInfo    =
3982                 {
3983                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3984                         DE_NULL,
3985                         externalType
3986                 };
3987                 const vk::VkPhysicalDeviceImageFormatInfo2                              info                    =
3988                 {
3989                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3990                         &externalInfo,
3991
3992                         format,
3993                         type,
3994                         tiling,
3995                         usageFlag,
3996                         createFlag,
3997                 };
3998                 vk::VkExternalImageFormatProperties                                             externalProperties      =
3999                 {
4000                         vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4001                         DE_NULL,
4002                         { 0u, 0u, 0u }
4003                 };
4004                 vk::VkImageFormatProperties2                                                    properties                      =
4005                 {
4006                         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4007                         &externalProperties,
4008                         {
4009                                 { 0u, 0u, 0u },
4010                                 0u,
4011                                 0u,
4012                                 0u,
4013                                 0u
4014                         }
4015                 };
4016
4017                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4018                         (deviceFeatures.sparseBinding == VK_FALSE))
4019                         continue;
4020
4021                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4022                         (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4023                         continue;
4024
4025                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4026                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4027                         continue;
4028
4029                 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4030                         continue;
4031                 }
4032
4033                 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4034                 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4035                 TCU_CHECK(externalProperties.pNext == DE_NULL);
4036                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4037
4038                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4039                 {
4040                         const bool      requiresDedicated       = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4041
4042                         if (!device || (requiresDedicated && !deviceHasDedicated))
4043                         {
4044                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4045                                 try
4046                                 {
4047                                         device                          = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4048                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4049                                         deviceHasDedicated      = requiresDedicated;
4050                                 }
4051                                 catch (const tcu::NotSupportedError& e)
4052                                 {
4053                                         log << e;
4054                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4055                                 }
4056                         }
4057                 }
4058
4059                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4060                 {
4061                         DE_ASSERT(!!device);
4062                         DE_ASSERT(vkd);
4063
4064                         if (deviceHasDedicated)
4065                         {
4066                                 // Memory requirements cannot be queried without binding the image.
4067                                 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4068                                         continue;
4069
4070                                 const vk::Unique<vk::VkImage>                           image                                           (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4071                                 const vk::VkMemoryDedicatedRequirements         reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *image));
4072                                 const bool                                                                      propertiesRequiresDedicated     = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4073                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
4074
4075                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
4076                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4077                         }
4078                         else
4079                         {
4080                                 // We can't query whether dedicated memory is required or not on per-object basis.
4081                                 // This check should be redundant as the code above tries to create device with
4082                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4083                                 // is required. However, checking again doesn't hurt.
4084                                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4085                         }
4086                 }
4087         }
4088
4089         return tcu::TestStatus::pass("Pass");
4090 }
4091
4092 struct ImageTestConfig
4093 {
4094                                                                                         ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits         externalType_,
4095                                                                                                                          bool                                                                           dedicated_)
4096                 : externalType  (externalType_)
4097                 , dedicated             (dedicated_)
4098         {
4099         }
4100
4101         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
4102         bool                                                                    dedicated;
4103 };
4104
4105 tcu::TestStatus testImageBindExportImportBind (Context&                                 context,
4106                                                                                            const ImageTestConfig        config)
4107 {
4108         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4109         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4110         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4111         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4112         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4113         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4114         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4115         const vk::VkImageUsageFlags                             usage                           = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
4116         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4117         const deUint32                                                  width                           = 64u;
4118         const deUint32                                                  height                          = 64u;
4119         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4120
4121         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4122
4123         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4124         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4125         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4126         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4127         NativeHandle                                                    handle;
4128
4129         VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4130
4131         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4132
4133         {
4134                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4135                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4136                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4137                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4138                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4139
4140                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4141         }
4142
4143         return tcu::TestStatus::pass("Pass");
4144 }
4145
4146 tcu::TestStatus testImageExportBindImportBind (Context&                                 context,
4147                                                                                            const ImageTestConfig        config)
4148 {
4149         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4150         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4151         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4152         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4153         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4154         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4155         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4156         const vk::VkImageUsageFlags                             usage                           = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
4157         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4158         const deUint32                                                  width                           = 64u;
4159         const deUint32                                                  height                          = 64u;
4160         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4161
4162         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4163
4164         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4165         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4166         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4167         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4168         NativeHandle                                                    handle;
4169
4170         if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4171         {
4172                 // AHB required the image memory to be bound first.
4173                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4174                 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4175         }
4176         else
4177         {
4178                 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4179                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4180         }
4181
4182         {
4183                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4184                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4185                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4186                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4187                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4188
4189                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4190         }
4191
4192         return tcu::TestStatus::pass("Pass");
4193 }
4194
4195 tcu::TestStatus testImageExportImportBindBind (Context&                                 context,
4196                                                                                            const ImageTestConfig        config)
4197 {
4198         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4199         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4200         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4201         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4202         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4203         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4204         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4205         const vk::VkImageUsageFlags                             usage                           = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
4206         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4207         const deUint32                                                  width                           = 64u;
4208         const deUint32                                                  height                          = 64u;
4209         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4210
4211         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4212
4213         if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4214         {
4215                 // AHB required the image memory to be bound first, which is not possible in this test.
4216                 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4217         }
4218
4219         // \note Image is only allocated to get memory requirements
4220         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4221         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4222         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4223         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4224         NativeHandle                                                    handle;
4225
4226         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4227
4228         {
4229                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4230                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4231                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4232                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4233                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4234
4235                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4236                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4237         }
4238
4239         return tcu::TestStatus::pass("Pass");
4240 }
4241
4242 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4243 {
4244         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4245                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4246 }
4247
4248 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4249 {
4250         const Transference transference (getHandelTypeTransferences(config.externalType));
4251         if (transference == TRANSFERENCE_COPY)
4252                 checkEvent(context, config);
4253 }
4254
4255 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4256 {
4257         const struct
4258         {
4259                 const char* const       name;
4260                 const Permanence        permanence;
4261         } permanences[] =
4262         {
4263                 { "temporary", PERMANENCE_TEMPORARY     },
4264                 { "permanent", PERMANENCE_PERMANENT     }
4265         };
4266
4267         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4268
4269         addFunctionCase(fenceGroup.get(), "info",       "Test external fence queries.", testFenceQueries,       externalType);
4270
4271         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4272         {
4273                 const Permanence                permanence              (permanences[permanenceNdx].permanence);
4274                 const char* const               permanenceName  (permanences[permanenceNdx].name);
4275                 const FenceTestConfig   config                  (externalType, permanence);
4276
4277                 if (!isSupportedPermanence(externalType, permanence))
4278                         continue;
4279
4280                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4281                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4282                 {
4283                         addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName,        "Test creating fence with win32 properties.",   testFenceWin32Create,   config);
4284                 }
4285
4286                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName,                            "Test importing fence twice.",                                                                                  checkSupport,   initProgramsToGetNativeFd,      testFenceImportTwice,                           config);
4287                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName,                                        "Test importing again over previously imported fence.",                                 checkSupport,   initProgramsToGetNativeFd,      testFenceImportReimport,                        config);
4288                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,           "Test importing fence multiple times.",                                                                 checkSupport,   initProgramsToGetNativeFd,      testFenceMultipleImports,                       config);
4289                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,       "Test signaling, exporting, importing and waiting for the sempahore.",  checkEvent,             initProgramsToGetNativeFd,      testFenceSignalExportImportWait,        config);
4290                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName,                           "Test signaling and importing the fence.",                                                              checkSupport,   initProgramsToGetNativeFd,      testFenceSignalImport,                          config);
4291                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName,                                           "Test resetting the fence.",                                                                                    checkEvent,             initProgramsToGetNativeFd,      testFenceReset,                                         config);
4292                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName,                            "Test fences transference.",                                                                                    checkEvent,             initProgramsToGetNativeFd,      testFenceTransference,                          config);
4293
4294                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4295                 {
4296                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName,                 "Test import signaled fence fd.",                                                                               initProgramsToGetNativeFd,      testFenceImportSyncFdSignaled,          config);
4297                 }
4298
4299                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4300                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4301                 {
4302                         // \note Not supported on WIN32 handles
4303                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,   "Test exporting fence multiple times.",         checkSupport,   initProgramsToGetNativeFd,      testFenceMultipleExports,       config);
4304
4305                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName,                                             "Test calling dup() on exported fence.",        checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup,                         config);
4306                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName,                                    "Test calling dup2() on exported fence.",       checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup2,                        config);
4307                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName,                                    "Test calling dup3() on exported fence.",       checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup3,                        config);
4308                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,                "Test sending fence fd over socket.",           checkSupport,   initProgramsToGetNativeFd,      testFenceFdSendOverSocket,      config);
4309                 }
4310
4311                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4312                 {
4313                         addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,                  "Test signaling and then waiting for the the sepmahore.",                       testFenceSignalWaitImport,                      config);
4314                         addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,   "Test exporting, signaling, importing and waiting for the fence.",      testFenceExportSignalImportWait,        config);
4315                         addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,   "Test exporting, importing, signaling and waiting for the fence.",      testFenceExportImportSignalWait,        config);
4316                 }
4317         }
4318
4319         return fenceGroup;
4320 }
4321
4322 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4323 {
4324         DE_UNREF(createFlag);
4325
4326         AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4327         if (!ahbApi)
4328         {
4329                 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4330         }
4331
4332 #if (DE_OS == DE_OS_ANDROID)
4333         // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4334         if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4335                 return false;
4336 #endif
4337
4338         vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4339         if (ahb.internal == DE_NULL)
4340         {
4341                 enableMaxLayerTest = false;
4342                 // try again with layerCount '1'
4343                 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4344                 if (ahb.internal == DE_NULL)
4345                 {
4346                         return false;
4347                 }
4348         }
4349         NativeHandle nativeHandle(ahb);
4350
4351         const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4352         const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4353
4354         for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4355         {
4356                 // Both mappings should be equivalent and work.
4357                 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4358
4359                 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4360                 {
4361                         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4362                         DE_NULL,
4363                         vk::VK_FORMAT_UNDEFINED,
4364                         0u,
4365                         0u,
4366                         mapping,
4367                         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4368                         vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4369                         vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4370                         vk::VK_CHROMA_LOCATION_COSITED_EVEN
4371                 };
4372
4373                 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4374                 {
4375                         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4376                         &formatProperties,
4377                         0u,
4378                         0u
4379                 };
4380
4381                 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4382                 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4383                 TCU_CHECK(formatProperties.format == format);
4384                 TCU_CHECK(formatProperties.externalFormat != 0u);
4385                 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4386                 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4387         }
4388
4389         return true;
4390 }
4391
4392 tcu::TestStatus testAndroidHardwareBufferImageFormat  (Context& context, vk::VkFormat format)
4393 {
4394         AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4395         if (!ahbApi)
4396         {
4397                 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4398         }
4399
4400         const vk::VkExternalMemoryHandleTypeFlagBits  externalMemoryType  =     vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4401         const vk::PlatformInterface&                              vkp                                   (context.getPlatformInterface());
4402         const CustomInstance                                              instance                              (createTestInstance(context, 0u, externalMemoryType, 0u));
4403         const vk::InstanceDriver&                                         vki                                   (instance.getDriver());
4404         const vk::VkPhysicalDevice                                        physicalDevice                (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4405
4406         vk::VkPhysicalDeviceProtectedMemoryFeatures             protectedFeatures;
4407         protectedFeatures.sType                         = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4408         protectedFeatures.pNext                         = DE_NULL;
4409         protectedFeatures.protectedMemory       = VK_FALSE;
4410
4411         vk::VkPhysicalDeviceFeatures2                                   deviceFeatures;
4412         deviceFeatures.sType            = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4413         deviceFeatures.pNext            = &protectedFeatures;
4414
4415         vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4416
4417         const deUint32                                                            queueFamilyIndex              (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4418         const vk::Unique<vk::VkDevice>                            device                                (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4419         const vk::DeviceDriver                                            vkd                                   (vkp, instance, *device);
4420         TestLog&                                                                          log                             = context.getTestContext().getLog();
4421         const vk::VkPhysicalDeviceLimits                          limits                          = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4422
4423         const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4424                                                                                                                                                                                    : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4425
4426         const vk::VkImageUsageFlagBits                            usageFlags[]            =
4427         {
4428                 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4429                 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4430                 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4431                 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4432                 framebufferUsageFlag,
4433         };
4434         const vk::VkImageCreateFlagBits                           createFlags[]           =
4435         {
4436                 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4437                 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4438                 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4439                 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4440         };
4441         const vk::VkImageTiling                                           tilings[]                       =
4442         {
4443                 vk::VK_IMAGE_TILING_OPTIMAL,
4444                 vk::VK_IMAGE_TILING_LINEAR,
4445         };
4446         deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4447         const size_t    one                                                     = 1u;
4448         const size_t    numOfUsageFlags                         = DE_LENGTH_OF_ARRAY(usageFlags);
4449         const size_t    numOfCreateFlags                        = DE_LENGTH_OF_ARRAY(createFlags);
4450         const size_t    numOfFlagCombos                         = one << (numOfUsageFlags + numOfCreateFlags);
4451         const size_t    numOfTilings                            = DE_LENGTH_OF_ARRAY(tilings);
4452
4453         for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4454         {
4455                 vk::VkImageUsageFlags   usage                           = 0;
4456                 vk::VkImageCreateFlags  createFlag                      = 0;
4457                 deUint64                                requiredAhbUsage        = 0;
4458                 bool                                    enableMaxLayerTest      = true;
4459                 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4460                 {
4461                         if ((combo & (one << usageNdx)) == 0)
4462                                 continue;
4463                         usage |= usageFlags[usageNdx];
4464                         requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4465                 }
4466                 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4467                 {
4468                         const size_t    bit     = numOfUsageFlags + createFlagNdx;
4469                         if ((combo & (one << bit)) == 0)
4470                                 continue;
4471                         if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4472                                 (protectedFeatures.protectedMemory == VK_FALSE))
4473                                 continue;
4474
4475                         createFlag |= createFlags[createFlagNdx];
4476                         requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4477                 }
4478
4479                 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4480                 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4481                         continue;
4482
4483                 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4484                 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4485                         continue;
4486
4487                 bool foundAnyUsableTiling = false;
4488                 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4489                 {
4490                         const vk::VkImageTiling tiling = tilings[tilingIndex];
4491
4492                         const vk::VkPhysicalDeviceExternalImageFormatInfo       externalInfo            =
4493                         {
4494                                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4495                                 DE_NULL,
4496                                 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4497                         };
4498                         const vk::VkPhysicalDeviceImageFormatInfo2                      info                            =
4499                         {
4500                                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4501                                 &externalInfo,
4502                                 format,
4503                                 vk::VK_IMAGE_TYPE_2D,
4504                                 tiling,
4505                                 usage,
4506                                 createFlag,
4507                         };
4508
4509                         vk::VkAndroidHardwareBufferUsageANDROID                         ahbUsageProperties      =
4510                         {
4511                                 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4512                                 DE_NULL,
4513                                 0u
4514                         };
4515                         vk::VkExternalImageFormatProperties                                     externalProperties      =
4516                         {
4517                                 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4518                                 &ahbUsageProperties,
4519                                 { 0u, 0u, 0u }
4520                         };
4521                         vk::VkImageFormatProperties2                                            properties                      =
4522                         {
4523                                 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4524                                 &externalProperties,
4525                                 {
4526                                         { 0u, 0u, 0u },
4527                                         0u,
4528                                         0u,
4529                                         0u,
4530                                         0u
4531                                 }
4532                         };
4533
4534                         if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4535                         {
4536                                 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4537                                 continue;
4538                         }
4539
4540                         foundAnyUsableTiling = true;
4541
4542                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4543                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4544                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4545                         deUint32 maxWidth   = properties.imageFormatProperties.maxExtent.width;
4546                         deUint32 maxHeight  = properties.imageFormatProperties.maxExtent.height;
4547                         TCU_CHECK(maxWidth >= 4096);
4548                         TCU_CHECK(maxHeight >= 4096);
4549                         // Even if not requested, at least one of GPU_* usage flags must be present.
4550                         TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4551                         // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4552                         TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4553
4554                         log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4555                                 << TestLog::EndMessage;
4556
4557                         struct ImageSize
4558                         {
4559                                 deUint32 width;
4560                                 deUint32 height;
4561                         };
4562                         ImageSize sizes[] =
4563                         {
4564                                 {64u, 64u},
4565                                 {1024u, 2096u},
4566                         };
4567
4568                         deUint32 exportedMemoryTypeIndex = 0;
4569
4570                         if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4571                         {
4572                                 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4573
4574                                 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4575                                 {
4576                                         if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4577                                         {
4578                                                 exportedMemoryTypeIndex = memoryTypeIndex;
4579                                                 break;
4580                                         }
4581                                 }
4582                         }
4583
4584                         for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4585                         {
4586                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4587                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4588                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4589                                 NativeHandle                                                    handle;
4590
4591                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4592                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4593
4594                                 deUint32 ahbFormat = 0;
4595                                 deUint64 anhUsage  = 0;
4596                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4597                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4598                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4599
4600                                 // Let watchdog know we're alive
4601                                 context.getTestContext().touchWatchdog();
4602                         }
4603
4604                         if (properties.imageFormatProperties.maxMipLevels >= 7u)
4605                         {
4606                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4607                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4608                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4609                                 NativeHandle                                                    handle;
4610
4611                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4612                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4613
4614                                 deUint32 ahbFormat = 0;
4615                                 deUint64 anhUsage  = 0;
4616                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4617                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4618                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4619                         }
4620
4621                         if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4622                         {
4623                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4624                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4625                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4626                                 NativeHandle                                                    handle;
4627
4628                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4629                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4630
4631                                 deUint32 ahbFormat = 0;
4632                                 deUint64 anhUsage  = 0;
4633                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4634                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4635                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4636                         }
4637                 }
4638
4639                 TCU_CHECK(foundAnyUsableTiling);
4640         }
4641         return tcu::TestStatus::pass("Pass");
4642 }
4643
4644 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4645 {
4646         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4647
4648         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4649         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4650         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4651         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4652
4653         return fenceGroup;
4654 }
4655
4656 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4657 {
4658         const struct
4659         {
4660                 const char* const       name;
4661                 const Permanence        permanence;
4662         } permanences[] =
4663         {
4664                 { "temporary", PERMANENCE_TEMPORARY     },
4665                 { "permanent", PERMANENCE_PERMANENT     }
4666         };
4667         const struct
4668         {
4669                 const char* const       name;
4670                 vk::VkSemaphoreType     type;
4671         } semaphoreTypes[] =
4672         {
4673                 { "binary",             vk::VK_SEMAPHORE_TYPE_BINARY },
4674                 { "timeline",   vk::VK_SEMAPHORE_TYPE_TIMELINE },
4675         };
4676
4677         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4678
4679         for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4680         {
4681                 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4682                                                 "Test external semaphore queries.",     testSemaphoreQueries,
4683                                                 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4684         }
4685
4686         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4687         {
4688                 const Permanence                        permanence              (permanences[permanenceNdx].permanence);
4689                 const char* const                       permanenceName  (permanences[permanenceNdx].name);
4690                 const SemaphoreTestConfig       config                  (externalType, permanence);
4691
4692                 if (!isSupportedPermanence(externalType, permanence))
4693                         continue;
4694
4695                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4696                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4697                 {
4698                         addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,    "Test creating semaphore with win32 properties.",       testSemaphoreWin32Create,       config);
4699                 }
4700
4701                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName,                                "Test importing semaphore twice.",                                                                              checkSupport,   initProgramsToGetNativeFd,      testSemaphoreImportTwice,                               config);
4702                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName,                                    "Test importing again over previously imported semaphore.",                             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreImportReimport,                    config);
4703                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,               "Test importing semaphore multiple times.",                                                             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreMultipleImports,                   config);
4704                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,   "Test signaling, exporting, importing and waiting for the sempahore.",  checkEvent,             initProgramsToGetNativeFd,      testSemaphoreSignalExportImportWait,    config);
4705                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName,                               "Test signaling and importing the semaphore.",                                                  checkSupport,   initProgramsToGetNativeFd,      testSemaphoreSignalImport,                              config);
4706                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName,                                "Test semaphores transference.",                                                                                checkEvent,             initProgramsToGetNativeFd,      testSemaphoreTransference,                              config);
4707
4708                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4709                 {
4710                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName,                     "Test import signaled semaphore fd.",                                                                           initProgramsToGetNativeFd,      testSemaphoreImportSyncFdSignaled,      config);
4711                 }
4712
4713
4714                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4715                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4716                 {
4717                         // \note Not supported on WIN32 handles
4718                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,       "Test exporting semaphore multiple times.",             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreMultipleExports,   config);
4719
4720                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName,                                         "Test calling dup() on exported semaphore.",    checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup,                             config);
4721                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName,                                        "Test calling dup2() on exported semaphore.",   checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup2,                    config);
4722                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName,                                        "Test calling dup3() on exported semaphore.",   checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup3,                    config);
4723                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,            "Test sending semaphore fd over socket.",               checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdSendOverSocket,  config);
4724                 }
4725
4726                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4727                 {
4728                         addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,                      "Test signaling and then waiting for the the sepmahore.",                               testSemaphoreSignalWaitImport,                  config);
4729                         addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,       "Test exporting, signaling, importing and waiting for the semaphore.",  testSemaphoreExportSignalImportWait,    config);
4730                         addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,       "Test exporting, importing, signaling and waiting for the semaphore.",  checkEvent,             testSemaphoreExportImportSignalWait,    config);
4731                 }
4732         }
4733
4734         return semaphoreGroup;
4735 }
4736
4737 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4738 {
4739         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4740
4741         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4742         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4743         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4744         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4745
4746         return semaphoreGroup;
4747 }
4748
4749 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4750 {
4751         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4752
4753         for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4754         {
4755                 const bool                                              dedicated               (dedicatedNdx == 1);
4756                 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup  (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4757
4758                 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4759                 {
4760                         const bool                                              hostVisible                     (hostVisibleNdx == 1);
4761                         de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup        (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4762                         const MemoryTestConfig                  memoryConfig            (externalType, hostVisible, dedicated);
4763
4764                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4765                                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4766                         {
4767                                 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .",         testMemoryWin32Create,  memoryConfig);
4768                         }
4769
4770                         addFunctionCase(hostVisibleGroup.get(), "import_twice",                         "Test importing memory object twice.",                  testMemoryImportTwice,          memoryConfig);
4771                         addFunctionCase(hostVisibleGroup.get(), "import_multiple_times",        "Test importing memory object multiple times.", testMemoryMultipleImports,      memoryConfig);
4772
4773                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4774                                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4775                         {
4776                                 addFunctionCase(hostVisibleGroup.get(), "dup",                                          "Test calling dup() on exported memory.",       testMemoryFdDup,                        memoryConfig);
4777                                 addFunctionCase(hostVisibleGroup.get(), "dup2",                                         "Test calling dup2() on exported memory.",      testMemoryFdDup2,                       memoryConfig);
4778                                 addFunctionCase(hostVisibleGroup.get(), "dup3",                                         "Test calling dup3() on exported memory.",      testMemoryFdDup3,                       memoryConfig);
4779                                 addFunctionCase(hostVisibleGroup.get(), "send_over_socket",                     "Test sending memory fd over socket.",          testMemoryFdSendOverSocket,     memoryConfig);
4780                                 // \note Not supported on WIN32 handles
4781                                 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times",        "Test exporting memory multiple times.",        testMemoryMultipleExports,      memoryConfig);
4782                         }
4783
4784                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4785                         {
4786                                 addFunctionCase(hostVisibleGroup.get(), "fd_properties",                        "Test obtaining the FD memory properties",      testMemoryFdProperties,         memoryConfig);
4787                         }
4788
4789                         dedicatedGroup->addChild(hostVisibleGroup.release());
4790                 }
4791
4792                 {
4793                         de::MovePtr<tcu::TestCaseGroup> bufferGroup             (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4794                         const BufferTestConfig                  bufferConfig    (externalType, dedicated);
4795
4796                         addFunctionCase(bufferGroup.get(), "info",                                              "External buffer memory info query.",                                           testBufferQueries,                              externalType);
4797                         addFunctionCase(bufferGroup.get(), "bind_export_import_bind",   "Test binding, exporting, importing and binding buffer.",       testBufferBindExportImportBind, bufferConfig);
4798                         addFunctionCase(bufferGroup.get(), "export_bind_import_bind",   "Test exporting, binding, importing and binding buffer.",       testBufferExportBindImportBind, bufferConfig);
4799                         addFunctionCase(bufferGroup.get(), "export_import_bind_bind",   "Test exporting, importing and binding buffer.",                        testBufferExportImportBindBind, bufferConfig);
4800
4801                         dedicatedGroup->addChild(bufferGroup.release());
4802                 }
4803
4804                 {
4805                         de::MovePtr<tcu::TestCaseGroup> imageGroup      (new tcu::TestCaseGroup(testCtx, "image", ""));
4806                         const ImageTestConfig                   imageConfig     (externalType, dedicated);
4807
4808                         addFunctionCase(imageGroup.get(), "info",                                               "External image memory info query.",                                            testImageQueries,                               externalType);
4809                         addFunctionCase(imageGroup.get(), "bind_export_import_bind",    "Test binding, exporting, importing and binding image.",        testImageBindExportImportBind,  imageConfig);
4810                         addFunctionCase(imageGroup.get(), "export_bind_import_bind",    "Test exporting, binding, importing and binding image.",        testImageExportBindImportBind,  imageConfig);
4811                         addFunctionCase(imageGroup.get(), "export_import_bind_bind",    "Test exporting, importing and binding image.",                         testImageExportImportBindBind,  imageConfig);
4812
4813                         dedicatedGroup->addChild(imageGroup.release());
4814                 }
4815
4816                 group->addChild(dedicatedGroup.release());
4817         }
4818
4819         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4820         {
4821                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4822
4823                 const vk::VkFormat      ahbFormats[]    =
4824                 {
4825                         vk::VK_FORMAT_R8G8B8_UNORM,
4826                         vk::VK_FORMAT_R8G8B8A8_UNORM,
4827                         vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4828                         vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4829                         vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4830                         vk::VK_FORMAT_D16_UNORM,
4831                         vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4832                         vk::VK_FORMAT_D24_UNORM_S8_UINT,
4833                         vk::VK_FORMAT_D32_SFLOAT,
4834                         vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4835                         vk::VK_FORMAT_S8_UINT,
4836                 };
4837                 const size_t            numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4838
4839                 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4840                 {
4841                         const vk::VkFormat      format                  = ahbFormats[ahbFormatNdx];
4842                         const std::string       testCaseName    = getFormatCaseName(format);
4843
4844                         addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4845                 }
4846
4847                 group->addChild(formatGroup.release());
4848         }
4849
4850         return group;
4851 }
4852
4853 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4854 {
4855         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4856
4857         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4858         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4859         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4860         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4861         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4862
4863         return group;
4864 }
4865
4866 } // anonymous
4867
4868 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4869 {
4870         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4871
4872         group->addChild(createSemaphoreTests(testCtx).release());
4873         group->addChild(createMemoryTests(testCtx).release());
4874         group->addChild(createFenceTests(testCtx).release());
4875
4876         return group.release();
4877 }
4878
4879 } // api
4880 } // vkt