039d0b542ebbcbf490477b3f56df293c5a96a022
[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                         if (transference == TRANSFERENCE_COPY)
1452                         {
1453                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1454                                 if (handle.getFd() == -1)
1455                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1456                         }
1457                         else
1458                                 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1459                 }
1460
1461                 submitEmptySignal(vkd, queue, *semaphore);
1462                 submitEmptyWait(vkd, queue, *semaphore);
1463
1464                 VK_CHECK(vkd.queueWaitIdle(queue));
1465         }
1466
1467         return tcu::TestStatus::pass("Pass");
1468 }
1469
1470 tcu::TestStatus testSemaphoreMultipleImports (Context&                                  context,
1471                                                                                           const SemaphoreTestConfig     config)
1472 {
1473         const size_t                                            importCount                     = 4 * 1024;
1474         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1475         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1476         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1477         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1478         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1479         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1480
1481         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1482
1483         {
1484                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1485                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1486                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1487                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1488                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1489                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1490                 NativeHandle                                            handleA;
1491
1492                 if (transference == TRANSFERENCE_COPY)
1493                 {
1494                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1495                         if (handleA.getFd() == -1)
1496                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1497                 }
1498                 else
1499                         getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1500
1501                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1502                 {
1503                         NativeHandle                                            handleB         (handleA);
1504                         const vk::Unique<vk::VkSemaphore>       semaphoreB      (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1505                 }
1506
1507                 if (transference == TRANSFERENCE_COPY)
1508                 {
1509                         importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1510                         submitEmptyWait(vkd, queue, *semaphoreA);
1511                 }
1512                 else if (transference == TRANSFERENCE_REFERENCE)
1513                 {
1514                         submitEmptySignal(vkd, queue, *semaphoreA);
1515                         submitEmptyWait(vkd, queue, *semaphoreA);
1516                 }
1517                 else
1518                         DE_FATAL("Unknown transference.");
1519
1520                 VK_CHECK(vkd.queueWaitIdle(queue));
1521         }
1522
1523         return tcu::TestStatus::pass("Pass");
1524 }
1525
1526 tcu::TestStatus testSemaphoreTransference (Context&                                             context,
1527                                                                                    const SemaphoreTestConfig    config)
1528 {
1529         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1530         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1531         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1532         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1533         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1534         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1535
1536         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1537
1538         {
1539                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1540                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context,  vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1541                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1542                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1543                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1544
1545                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1546                 NativeHandle                                            handle;
1547
1548                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1549                 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1550                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1551
1552                 {
1553                         const vk::Unique<vk::VkSemaphore>       semaphoreB                      (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1554
1555                         if (config.permanence == PERMANENCE_PERMANENT)
1556                         {
1557                                 if (transference == TRANSFERENCE_COPY)
1558                                 {
1559                                         submitEmptySignal(vkd, queue, *semaphoreA);
1560                                         submitEmptyWait(vkd, queue, *semaphoreB);
1561                                         VK_CHECK(vkd.queueWaitIdle(queue));
1562
1563                                         submitEmptySignal(vkd, queue, *semaphoreB);
1564
1565                                         submitEmptyWait(vkd, queue, *semaphoreA);
1566                                         submitEmptyWait(vkd, queue, *semaphoreB);
1567                                         VK_CHECK(vkd.queueWaitIdle(queue));
1568                                 }
1569                                 else if (transference== TRANSFERENCE_REFERENCE)
1570                                 {
1571                                         submitEmptyWait(vkd, queue, *semaphoreB);
1572                                         VK_CHECK(vkd.queueWaitIdle(queue));
1573
1574                                         submitEmptySignal(vkd, queue, *semaphoreA);
1575                                         submitEmptyWait(vkd, queue, *semaphoreB);
1576
1577                                         submitEmptySignal(vkd, queue, *semaphoreB);
1578                                         submitEmptyWait(vkd, queue, *semaphoreA);
1579                                         VK_CHECK(vkd.queueWaitIdle(queue));
1580                                 }
1581                                 else
1582                                         DE_FATAL("Unknown transference.");
1583                         }
1584                         else if (config.permanence == PERMANENCE_TEMPORARY)
1585                         {
1586                                 if (transference == TRANSFERENCE_COPY)
1587                                 {
1588                                         submitEmptySignal(vkd, queue, *semaphoreA);
1589                                         submitEmptyWait(vkd, queue, *semaphoreB);
1590                                         VK_CHECK(vkd.queueWaitIdle(queue));
1591
1592                                         submitEmptySignal(vkd, queue, *semaphoreB);
1593
1594                                         submitEmptyWait(vkd, queue, *semaphoreA);
1595                                         submitEmptyWait(vkd, queue, *semaphoreB);
1596                                         VK_CHECK(vkd.queueWaitIdle(queue));
1597                                 }
1598                                 else if (transference== TRANSFERENCE_REFERENCE)
1599                                 {
1600                                         submitEmptyWait(vkd, queue, *semaphoreB);
1601                                         VK_CHECK(vkd.queueWaitIdle(queue));
1602
1603                                         submitEmptySignal(vkd, queue, *semaphoreA);
1604                                         submitEmptySignal(vkd, queue, *semaphoreB);
1605
1606                                         submitEmptyWait(vkd, queue, *semaphoreB);
1607                                         submitEmptyWait(vkd, queue, *semaphoreA);
1608                                         VK_CHECK(vkd.queueWaitIdle(queue));
1609                                 }
1610                                 else
1611                                         DE_FATAL("Unknown transference.");
1612                         }
1613                         else
1614                                 DE_FATAL("Unknown permanence.");
1615                 }
1616
1617                 return tcu::TestStatus::pass("Pass");
1618         }
1619 }
1620
1621 tcu::TestStatus testSemaphoreFdDup (Context&                                    context,
1622                                                                         const SemaphoreTestConfig       config)
1623 {
1624 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1625         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1626         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1627         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1628         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1629         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1630         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1631
1632         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1633
1634         {
1635                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1636                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1637                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1638                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1639                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1640
1641                 TestLog&                                                        log                     = context.getTestContext().getLog();
1642                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1643
1644                 {
1645                         NativeHandle            fd;
1646
1647                         if (transference == TRANSFERENCE_COPY)
1648                         {
1649                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1650                                 if (fd.getFd() == -1)
1651                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1652                         }
1653                         else
1654                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1655
1656                         NativeHandle            newFd   (dup(fd.getFd()));
1657
1658                         if (newFd.getFd() < 0)
1659                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1660
1661                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1662
1663                         {
1664                                 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1665
1666                                 if (transference == TRANSFERENCE_COPY)
1667                                         submitEmptyWait(vkd, queue, *semaphoreB);
1668                                 else if (transference == TRANSFERENCE_REFERENCE)
1669                                 {
1670                                         submitEmptySignal(vkd, queue, *semaphoreA);
1671                                         submitEmptyWait(vkd, queue, *semaphoreB);
1672                                 }
1673                                 else
1674                                         DE_FATAL("Unknown permanence.");
1675
1676                                 VK_CHECK(vkd.queueWaitIdle(queue));
1677                         }
1678                 }
1679
1680                 return tcu::TestStatus::pass("Pass");
1681         }
1682 #else
1683         DE_UNREF(context);
1684         DE_UNREF(config);
1685         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1686 #endif
1687 }
1688
1689 tcu::TestStatus testSemaphoreFdDup2 (Context&                                   context,
1690                                                                          const SemaphoreTestConfig      config)
1691 {
1692 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1693         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1694         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1695         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1696         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1697         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1698         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1699
1700         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1701
1702         {
1703                 const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1704                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1705                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1706                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1707                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1708
1709                 TestLog&                                                        log                     = context.getTestContext().getLog();
1710                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1711                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1712
1713                 {
1714                         NativeHandle            fd, secondFd;
1715
1716                         if (transference == TRANSFERENCE_COPY)
1717                         {
1718                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1719                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1720                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1721                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1722                         }
1723                         else
1724                         {
1725                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1726                                 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1727                         }
1728
1729                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
1730
1731                         if (newFd < 0)
1732                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1733
1734                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1735
1736                         {
1737                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1738
1739                                 if (transference == TRANSFERENCE_COPY)
1740                                         submitEmptyWait(vkd, queue, *semaphoreC);
1741                                 else if (transference == TRANSFERENCE_REFERENCE)
1742                                 {
1743                                         submitEmptySignal(vkd, queue, *semaphoreA);
1744                                         submitEmptyWait(vkd, queue, *semaphoreC);
1745                                 }
1746                                 else
1747                                         DE_FATAL("Unknown permanence.");
1748
1749                                 VK_CHECK(vkd.queueWaitIdle(queue));
1750                         }
1751                 }
1752
1753                 return tcu::TestStatus::pass("Pass");
1754         }
1755 #else
1756         DE_UNREF(context);
1757         DE_UNREF(config);
1758         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1759 #endif
1760 }
1761
1762 tcu::TestStatus testSemaphoreFdDup3 (Context&                                   context,
1763                                                                          const SemaphoreTestConfig      config)
1764 {
1765 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1766         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1767         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1768         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1769         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1770         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1771         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1772
1773         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1774
1775         {
1776                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1777                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1778                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1779                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1780
1781                 TestLog&                                                        log                     = context.getTestContext().getLog();
1782                 const vk::Unique<vk::VkSemaphore>       semaphoreA      (createExportableSemaphore(vkd, *device, config.externalType));
1783                 const vk::Unique<vk::VkSemaphore>       semaphoreB      (createExportableSemaphore(vkd, *device, config.externalType));
1784
1785                 {
1786                         NativeHandle                                            fd, secondFd;
1787
1788                         if (transference == TRANSFERENCE_COPY)
1789                         {
1790                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1791                                 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1792                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1793                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1794                         }
1795                         else
1796                         {
1797                                 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1798                                 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1799                         }
1800
1801                         const vk::VkSemaphoreImportFlags        flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1802                         const int                                                       newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
1803
1804                         if (newFd < 0)
1805                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1806
1807                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1808
1809                         {
1810                                 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1811
1812                                 if (transference == TRANSFERENCE_COPY)
1813                                         submitEmptyWait(vkd, queue, *semaphoreC);
1814                                 else if (transference == TRANSFERENCE_REFERENCE)
1815                                 {
1816                                         submitEmptySignal(vkd, queue, *semaphoreA);
1817                                         submitEmptyWait(vkd, queue, *semaphoreC);
1818                                 }
1819                                 else
1820                                         DE_FATAL("Unknown permanence.");
1821
1822                                 VK_CHECK(vkd.queueWaitIdle(queue));
1823                         }
1824                 }
1825
1826                 return tcu::TestStatus::pass("Pass");
1827         }
1828 #else
1829         DE_UNREF(context);
1830         DE_UNREF(config);
1831         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1832 #endif
1833 }
1834
1835 tcu::TestStatus testSemaphoreFdSendOverSocket (Context&                                         context,
1836                                                                                            const SemaphoreTestConfig    config)
1837 {
1838 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1839         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
1840         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
1841         const CustomInstance                            instance                        (createTestInstance(context, config.externalType, 0u, 0u));
1842         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
1843         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1844         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1845
1846         checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1847
1848         {
1849                 const vk::Unique<vk::VkDevice>          device          (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1850                 const vk::DeviceDriver                          vkd                     (vkp, instance, *device);
1851                 vk::SimpleAllocator                                     alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1852                 const vk::VkQueue                                       queue           (getQueue(vkd, *device, queueFamilyIndex));
1853
1854                 TestLog&                                                        log                     = context.getTestContext().getLog();
1855                 const vk::Unique<vk::VkSemaphore>       semaphore       (createExportableSemaphore(vkd, *device, config.externalType));
1856                 NativeHandle                                            fd;
1857
1858                 if (transference == TRANSFERENCE_COPY)
1859                 {
1860                         submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1861                         if (fd.getFd() == -1)
1862                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1863                 }
1864                 else
1865                         getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1866
1867                 {
1868                         int sv[2];
1869
1870                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1871                         {
1872                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1873                                 TCU_FAIL("Failed to create socket pair");
1874                         }
1875
1876                         {
1877                                 const NativeHandle      srcSocket       (sv[0]);
1878                                 const NativeHandle      dstSocket       (sv[1]);
1879                                 std::string                     sendData        ("deqp");
1880
1881                                 // Send FD
1882                                 {
1883                                         const int                       fdRaw   (fd.getFd());
1884                                         msghdr                          msg;
1885                                         cmsghdr*                        cmsg;
1886                                         char                            buffer[CMSG_SPACE(sizeof(int))];
1887                                         iovec                           iov             = { &sendData[0], sendData.length()};
1888
1889                                         deMemset(&msg, 0, sizeof(msg));
1890
1891                                         msg.msg_control         = buffer;
1892                                         msg.msg_controllen      = sizeof(buffer);
1893                                         msg.msg_iovlen          = 1;
1894                                         msg.msg_iov                     = &iov;
1895
1896                                         cmsg                            = CMSG_FIRSTHDR(&msg);
1897                                         cmsg->cmsg_level        = SOL_SOCKET;
1898                                         cmsg->cmsg_type         = SCM_RIGHTS;
1899                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
1900
1901                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1902                                         msg.msg_controllen = cmsg->cmsg_len;
1903
1904                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1905                                         {
1906                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1907                                                 TCU_FAIL("Failed to send fd over socket");
1908                                         }
1909                                 }
1910
1911                                 // Recv FD
1912                                 {
1913                                         msghdr                  msg;
1914                                         char                    buffer[CMSG_SPACE(sizeof(int))];
1915                                         std::string             recvData        (4, '\0');
1916                                         iovec                   iov                     = { &recvData[0], recvData.length() };
1917
1918                                         deMemset(&msg, 0, sizeof(msg));
1919
1920                                         msg.msg_control         = buffer;
1921                                         msg.msg_controllen      = sizeof(buffer);
1922                                         msg.msg_iovlen          = 1;
1923                                         msg.msg_iov                     = &iov;
1924
1925                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1926
1927                                         if (bytes < 0)
1928                                         {
1929                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1930                                                 TCU_FAIL("Failed to recv fd over socket");
1931
1932                                         }
1933                                         else if (bytes != (ssize_t)sendData.length())
1934                                         {
1935                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1936                                         }
1937                                         else
1938                                         {
1939                                                 const vk::VkSemaphoreImportFlags        flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1940                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
1941                                                 int                                                                     newFd_;
1942                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1943                                                 NativeHandle                                            newFd   (newFd_);
1944
1945                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1946                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1947                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1948                                                 TCU_CHECK(recvData == sendData);
1949                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1950
1951                                                 {
1952                                                         const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1953
1954                                                         if (transference == TRANSFERENCE_COPY)
1955                                                                 submitEmptyWait(vkd, queue, *newSemaphore);
1956                                                         else if (transference == TRANSFERENCE_REFERENCE)
1957                                                         {
1958                                                                 submitEmptySignal(vkd, queue, *newSemaphore);
1959                                                                 submitEmptyWait(vkd, queue, *newSemaphore);
1960                                                         }
1961                                                         else
1962                                                                 DE_FATAL("Unknown permanence.");
1963
1964                                                         VK_CHECK(vkd.queueWaitIdle(queue));
1965                                                 }
1966                                         }
1967                                 }
1968                         }
1969                 }
1970         }
1971
1972         return tcu::TestStatus::pass("Pass");
1973 #else
1974         DE_UNREF(context);
1975         DE_UNREF(config);
1976         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1977 #endif
1978 }
1979
1980 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1981 {
1982         const CustomInstance                                                    instance        (createTestInstance(context, 0u, 0u, externalType));
1983         const vk::InstanceDriver&                                               vki                     (instance.getDriver());
1984         const vk::VkPhysicalDevice                                              device          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1985
1986         TestLog&                                                                                log                     = context.getTestContext().getLog();
1987
1988         const vk::VkPhysicalDeviceExternalFenceInfo             info            =
1989         {
1990                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1991                 DE_NULL,
1992                 externalType
1993         };
1994         vk::VkExternalFenceProperties                                   properties      =
1995         {
1996                 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1997                 DE_NULL,
1998                 0u,
1999                 0u,
2000                 0u
2001         };
2002
2003         vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2004         log << TestLog::Message << properties << TestLog::EndMessage;
2005
2006         TCU_CHECK(properties.pNext == DE_NULL);
2007         TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2008
2009         return tcu::TestStatus::pass("Pass");
2010 }
2011
2012 struct FenceTestConfig
2013 {
2014                                                                                                 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits  externalType_,
2015                                                                                                                                  Permanence                                                                     permanence_)
2016                 : externalType          (externalType_)
2017                 , permanence            (permanence_)
2018         {
2019         }
2020
2021         vk::VkExternalFenceHandleTypeFlagBits   externalType;
2022         Permanence                                                              permanence;
2023 };
2024
2025 tcu::TestStatus testFenceWin32Create (Context&                          context,
2026                                                                           const FenceTestConfig config)
2027 {
2028 #if (DE_OS == DE_OS_WIN32)
2029         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2030         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2031         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2032         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2033         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2034         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2035
2036         checkFenceSupport(vki, physicalDevice, config.externalType);
2037
2038         {
2039                 const vk::Unique<vk::VkDevice>                          device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2040                 const vk::DeviceDriver                                          vkd                             (vkp, instance, *device);
2041                 const vk::VkQueue                                                       queue                   (getQueue(vkd, *device, queueFamilyIndex));
2042                 const vk::VkExportFenceWin32HandleInfoKHR       win32ExportInfo =
2043                 {
2044                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2045                         DE_NULL,
2046
2047                         (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2048                         DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2049                         (vk::pt::Win32LPCWSTR)DE_NULL
2050                 };
2051                 const vk::VkExportFenceCreateInfo                       exportCreateInfo=
2052                 {
2053                         vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2054                         &win32ExportInfo,
2055                         (vk::VkExternalFenceHandleTypeFlags)config.externalType
2056                 };
2057                 const vk::VkFenceCreateInfo                                     createInfo              =
2058                 {
2059                         vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2060                         &exportCreateInfo,
2061                         0u
2062                 };
2063                 const vk::Unique<vk::VkFence>                           fence                   (vk::createFence(vkd, *device, &createInfo));
2064
2065                 if (transference == TRANSFERENCE_COPY)
2066                         submitEmptySignal(vkd, queue, *fence);
2067
2068                 NativeHandle                                                            handleA;
2069                 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2070
2071                 {
2072                         const vk::VkFenceImportFlags                    flags                   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2073                         const vk::Unique<vk::VkFence>                   fenceA                  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2074
2075                         if (transference == TRANSFERENCE_COPY)
2076                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2077                         else if (transference == TRANSFERENCE_REFERENCE)
2078                         {
2079                                 submitEmptySignal(vkd, queue, *fence);
2080                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2081                         }
2082                         else
2083                                 DE_FATAL("Unknown transference.");
2084
2085                         VK_CHECK(vkd.queueWaitIdle(queue));
2086                 }
2087
2088                 return tcu::TestStatus::pass("Pass");
2089         }
2090 #else
2091         DE_UNREF(context);
2092         DE_UNREF(config);
2093         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2094 #endif
2095 }
2096
2097 tcu::TestStatus testFenceImportTwice (Context&                          context,
2098                                                                           const FenceTestConfig config)
2099 {
2100         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2101         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2102         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2103         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2104         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2105         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2106
2107         checkFenceSupport(vki, physicalDevice, config.externalType);
2108
2109         {
2110                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2111                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2112                 vk::SimpleAllocator                             alloc           (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2113                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2114                 const vk::Unique<vk::VkFence>   fence           (createExportableFence(vkd, *device, config.externalType));
2115                 NativeHandle                                    handleA;
2116
2117                 if (transference == TRANSFERENCE_COPY)
2118                 {
2119                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2120                         if (handleA.getFd() == -1)
2121                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2122                 }
2123                 else
2124                         getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2125
2126                 {
2127                         NativeHandle                                    handleB (handleA);
2128                         const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2129                         const vk::Unique<vk::VkFence>   fenceA  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2130                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2131
2132                         if (transference == TRANSFERENCE_COPY)
2133                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2134                         else if (transference == TRANSFERENCE_REFERENCE)
2135                         {
2136                                 submitEmptySignal(vkd, queue, *fenceA);
2137                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2138                         }
2139                         else
2140                                 DE_FATAL("Unknown transference.");
2141
2142                         VK_CHECK(vkd.queueWaitIdle(queue));
2143                 }
2144
2145                 return tcu::TestStatus::pass("Pass");
2146         }
2147 }
2148
2149 tcu::TestStatus testFenceImportReimport (Context&                               context,
2150                                                                                  const FenceTestConfig  config)
2151 {
2152         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2153         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2154         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2155         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2156         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2157         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2158
2159         checkFenceSupport(vki, physicalDevice, config.externalType);
2160
2161         {
2162                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2163                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2164                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2165                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2166
2167                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2168                 NativeHandle                                    handleA;
2169
2170                 if (transference == TRANSFERENCE_COPY)
2171                 {
2172                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2173                         if (handleA.getFd() == -1)
2174                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2175                 }
2176                 else
2177                         getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2178
2179                 NativeHandle                                    handleB (handleA);
2180                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2181                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2182
2183                 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2184
2185                 if (transference == TRANSFERENCE_COPY)
2186                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2187                 else if (transference == TRANSFERENCE_REFERENCE)
2188                 {
2189                         submitEmptySignal(vkd, queue, *fenceA);
2190                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2191                 }
2192                 else
2193                         DE_FATAL("Unknown transference.");
2194
2195                 VK_CHECK(vkd.queueWaitIdle(queue));
2196
2197                 return tcu::TestStatus::pass("Pass");
2198         }
2199 }
2200
2201 tcu::TestStatus testFenceSignalExportImportWait (Context&                               context,
2202                                                                                                  const FenceTestConfig  config)
2203 {
2204         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2205         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2206         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2207         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2208         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2209
2210         checkFenceSupport(vki, physicalDevice, config.externalType);
2211
2212         {
2213                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2214                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2215                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2216                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2217                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2218
2219                 {
2220                         NativeHandle    handle;
2221
2222                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2223                         if (handle.getFd() == -1)
2224                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2225
2226                         {
2227                                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2228                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2229                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2230
2231                                 VK_CHECK(vkd.queueWaitIdle(queue));
2232                         }
2233                 }
2234
2235                 return tcu::TestStatus::pass("Pass");
2236         }
2237 }
2238
2239 tcu::TestStatus testFenceImportSyncFdSignaled (Context&                                 context,
2240                                                                                            const FenceTestConfig        config)
2241 {
2242         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2243         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2244         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2245         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2246         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2247         const vk::VkFenceImportFlags            flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2248
2249         checkFenceSupport(vki, physicalDevice, config.externalType);
2250
2251         {
2252                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2253                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2254                 NativeHandle                                    handle  = -1;
2255                 const vk::Unique<vk::VkFence>   fence   (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2256
2257                 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2258                         return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2259
2260                 return tcu::TestStatus::pass("Pass");
2261         }
2262 }
2263
2264 tcu::TestStatus testFenceExportSignalImportWait (Context&                               context,
2265                                                                                                  const FenceTestConfig  config)
2266 {
2267         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2268         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2269         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2270         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2271         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2272         const vk::VkFenceImportFlags            flags                           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2273
2274         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2275         checkFenceSupport(vki, physicalDevice, config.externalType);
2276
2277         {
2278                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2279                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2280                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2281
2282                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2283                 NativeHandle                                    handle;
2284
2285                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2286
2287                 submitEmptySignal(vkd, queue, *fenceA);
2288                 {
2289                         {
2290                                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2291
2292                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2293                                 VK_CHECK(vkd.queueWaitIdle(queue));
2294                         }
2295                 }
2296
2297                 return tcu::TestStatus::pass("Pass");
2298         }
2299 }
2300
2301 tcu::TestStatus testFenceExportImportSignalWait (Context&                               context,
2302                                                                                                  const FenceTestConfig  config)
2303 {
2304         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2305         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2306         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2307         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2308         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2309
2310         DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2311         checkFenceSupport(vki, physicalDevice, config.externalType);
2312
2313         {
2314                 const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2315                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2316                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2317                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2318
2319                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2320                 NativeHandle                                    handle;
2321
2322                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2323
2324                 const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2325
2326                 submitEmptySignal(vkd, queue, *fenceA);
2327                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2328
2329                 VK_CHECK(vkd.queueWaitIdle(queue));
2330
2331                 return tcu::TestStatus::pass("Pass");
2332         }
2333 }
2334
2335 tcu::TestStatus testFenceSignalImport (Context&                                 context,
2336                                                                            const FenceTestConfig        config)
2337 {
2338         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2339         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2340         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2341         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2342         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2343         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2344
2345         checkFenceSupport(vki, physicalDevice, config.externalType);
2346
2347         {
2348                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2349                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2350                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2351                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2352                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2353
2354                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2355                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2356                 NativeHandle                                    handle;
2357
2358                 submitEmptySignal(vkd, queue, *fenceB);
2359                 VK_CHECK(vkd.queueWaitIdle(queue));
2360
2361                 if (transference == TRANSFERENCE_COPY)
2362                 {
2363                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2364                         if (handle.getFd() == -1)
2365                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2366                 }
2367                 else
2368                         getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2369
2370                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2371
2372                 if (transference == TRANSFERENCE_COPY)
2373                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2374                 else if (transference == TRANSFERENCE_REFERENCE)
2375                 {
2376                         submitEmptySignal(vkd, queue, *fenceA);
2377                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2378                 }
2379                 else
2380                         DE_FATAL("Unknown transference.");
2381
2382                 VK_CHECK(vkd.queueWaitIdle(queue));
2383
2384                 return tcu::TestStatus::pass("Pass");
2385         }
2386 }
2387
2388 tcu::TestStatus testFenceReset (Context&                                context,
2389                                                                 const FenceTestConfig   config)
2390 {
2391         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2392         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2393         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2394         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2395         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2396         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2397
2398         checkFenceSupport(vki, physicalDevice, config.externalType);
2399
2400         {
2401                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2402                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2403                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2404                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2405                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2406
2407                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2408                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2409                 const vk::Unique<vk::VkFence>   fenceC  (createFence(vkd, *device));
2410                 NativeHandle                                    handle;
2411
2412                 submitEmptySignal(vkd, queue, *fenceB);
2413                 VK_CHECK(vkd.queueWaitIdle(queue));
2414
2415                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2416                 if (handle.getFd() == -1)
2417                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2418
2419                 NativeHandle                                    handleB (handle);
2420                 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2421                 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2422
2423                 VK_CHECK(vkd.queueWaitIdle(queue));
2424                 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2425
2426                 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2427                 {
2428                         // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2429                         // or fenceB should be separate copy of the payload and not affect fenceC
2430                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2431
2432                         // vkResetFences() should have restored fenceBs prior state and should be now reset
2433                         // or fenceB should have it's separate payload
2434                         submitEmptySignal(vkd, queue, *fenceB);
2435                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2436                 }
2437                 else if (config.permanence == PERMANENCE_PERMANENT)
2438                 {
2439                         DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2440
2441                         // Reset fences should have reset all of the fences
2442                         submitEmptySignal(vkd, queue, *fenceC);
2443
2444                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2445                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2446                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2447                 }
2448                 else
2449                         DE_FATAL("Unknown permanence");
2450
2451                 VK_CHECK(vkd.queueWaitIdle(queue));
2452
2453                 return tcu::TestStatus::pass("Pass");
2454         }
2455 }
2456
2457 tcu::TestStatus testFenceSignalWaitImport (Context&                                     context,
2458                                                                                    const FenceTestConfig        config)
2459 {
2460         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2461         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2462         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2463         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2464         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2465
2466         checkFenceSupport(vki, physicalDevice, config.externalType);
2467
2468         {
2469                 const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2470                 const vk::Unique<vk::VkDevice>  device          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2471                 const vk::DeviceDriver                  vkd                     (vkp, instance, *device);
2472                 const vk::VkQueue                               queue           (getQueue(vkd, *device, queueFamilyIndex));
2473
2474                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2475                 const vk::Unique<vk::VkFence>   fenceB  (createFence(vkd, *device));
2476                 NativeHandle                                    handle;
2477
2478                 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2479
2480                 submitEmptySignal(vkd, queue, *fenceB);
2481                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2482
2483                 VK_CHECK(vkd.queueWaitIdle(queue));
2484
2485                 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2486
2487                 submitEmptySignal(vkd, queue, *fenceA);
2488                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2489
2490                 VK_CHECK(vkd.queueWaitIdle(queue));
2491
2492                 return tcu::TestStatus::pass("Pass");
2493         }
2494 }
2495
2496 tcu::TestStatus testFenceMultipleExports (Context&                              context,
2497                                                                                   const FenceTestConfig config)
2498 {
2499         const size_t                                            exportCount                     = 1024;
2500         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2501         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2502         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2503         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2504         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2505         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2506
2507         checkFenceSupport(vki, physicalDevice, config.externalType);
2508
2509         {
2510                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2511                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2512                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2513                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2514                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
2515
2516                 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2517                 {
2518                         NativeHandle handle;
2519
2520                         if (transference == TRANSFERENCE_COPY)
2521                         {
2522                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2523                                 if (handle.getFd() == -1)
2524                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2525                         }
2526                         else
2527                                 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2528                 }
2529
2530                 submitEmptySignal(vkd, queue, *fence);
2531                 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2532
2533                 VK_CHECK(vkd.queueWaitIdle(queue));
2534         }
2535
2536         return tcu::TestStatus::pass("Pass");
2537 }
2538
2539 tcu::TestStatus testFenceMultipleImports (Context&                              context,
2540                                                                                   const FenceTestConfig config)
2541 {
2542         const size_t                                            importCount                     = 4 * 1024;
2543         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2544         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2545         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2546         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2547         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2548         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2549
2550         checkFenceSupport(vki, physicalDevice, config.externalType);
2551
2552         {
2553                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2554                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2555                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2556                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2557                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2558                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2559                 NativeHandle                                    handleA;
2560
2561                 if (transference == TRANSFERENCE_COPY)
2562                 {
2563                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2564                         if (handleA.getFd() == -1)
2565                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2566                 }
2567                 else
2568                         getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2569
2570                 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2571                 {
2572                         NativeHandle                                    handleB         (handleA);
2573                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2574                 }
2575
2576                 if (transference == TRANSFERENCE_COPY)
2577                 {
2578                         importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2579                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2580                 }
2581                 else if (transference == TRANSFERENCE_REFERENCE)
2582                 {
2583                         submitEmptySignal(vkd, queue, *fenceA);
2584                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2585                 }
2586                 else
2587                         DE_FATAL("Unknown transference.");
2588
2589                 VK_CHECK(vkd.queueWaitIdle(queue));
2590         }
2591
2592         return tcu::TestStatus::pass("Pass");
2593 }
2594
2595 tcu::TestStatus testFenceTransference (Context&                                 context,
2596                                                                            const FenceTestConfig        config)
2597 {
2598         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2599         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2600         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2601         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2602         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2603         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2604
2605         checkFenceSupport(vki, physicalDevice, config.externalType);
2606
2607         {
2608                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2609                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2610                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2611                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2612                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2613
2614                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2615                 NativeHandle                                    handle;
2616
2617                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2618                 if (handle.getFd() == -1)
2619                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2620
2621                 {
2622                         const vk::Unique<vk::VkFence>   fenceB  (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2623
2624                         if (config.permanence == PERMANENCE_PERMANENT)
2625                         {
2626                                 if (transference == TRANSFERENCE_COPY)
2627                                 {
2628                                         submitEmptySignal(vkd, queue, *fenceA);
2629                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2630                                         VK_CHECK(vkd.queueWaitIdle(queue));
2631
2632                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2633                                         submitEmptySignal(vkd, queue, *fenceB);
2634
2635                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2636                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2637                                         VK_CHECK(vkd.queueWaitIdle(queue));
2638                                 }
2639                                 else if (transference== TRANSFERENCE_REFERENCE)
2640                                 {
2641                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2642                                         VK_CHECK(vkd.queueWaitIdle(queue));
2643
2644                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2645                                         submitEmptySignal(vkd, queue, *fenceA);
2646                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2647
2648                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2649                                         submitEmptySignal(vkd, queue, *fenceB);
2650                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2651                                         VK_CHECK(vkd.queueWaitIdle(queue));
2652                                 }
2653                                 else
2654                                         DE_FATAL("Unknown transference.");
2655                         }
2656                         else if (config.permanence == PERMANENCE_TEMPORARY)
2657                         {
2658                                 if (transference == TRANSFERENCE_COPY)
2659                                 {
2660                                         submitEmptySignal(vkd, queue, *fenceA);
2661                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2662                                         VK_CHECK(vkd.queueWaitIdle(queue));
2663
2664                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2665                                         submitEmptySignal(vkd, queue, *fenceB);
2666
2667                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2668                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2669                                         VK_CHECK(vkd.queueWaitIdle(queue));
2670                                 }
2671                                 else if (transference == TRANSFERENCE_REFERENCE)
2672                                 {
2673                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2674                                         VK_CHECK(vkd.queueWaitIdle(queue));
2675
2676                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2677                                         VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2678                                         submitEmptySignal(vkd, queue, *fenceA);
2679                                         submitEmptySignal(vkd, queue, *fenceB);
2680
2681                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2682                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2683                                         VK_CHECK(vkd.queueWaitIdle(queue));
2684                                 }
2685                                 else
2686                                         DE_FATAL("Unknown transference.");
2687                         }
2688                         else
2689                                 DE_FATAL("Unknown permanence.");
2690                 }
2691
2692                 return tcu::TestStatus::pass("Pass");
2693         }
2694 }
2695
2696 tcu::TestStatus testFenceFdDup (Context&                                context,
2697                                                                 const FenceTestConfig   config)
2698 {
2699 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2700         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2701         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2702         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2703         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2704         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2705         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2706
2707         checkFenceSupport(vki, physicalDevice, config.externalType);
2708
2709         {
2710                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2711                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2712                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2713                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2714                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2715
2716                 TestLog&                                                log             = context.getTestContext().getLog();
2717                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2718
2719                 {
2720                         NativeHandle            fd;
2721
2722                         if (transference == TRANSFERENCE_COPY)
2723                         {
2724                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2725                                 if (fd.getFd() == -1)
2726                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2727                         }
2728                         else
2729                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2730
2731                         NativeHandle            newFd   (dup(fd.getFd()));
2732
2733                         if (newFd.getFd() < 0)
2734                                 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2735
2736                         TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2737
2738                         {
2739                                 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2740
2741                                 if (transference == TRANSFERENCE_COPY)
2742                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2743                                 else if (transference == TRANSFERENCE_REFERENCE)
2744                                 {
2745                                         submitEmptySignal(vkd, queue, *fenceA);
2746                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2747                                 }
2748                                 else
2749                                         DE_FATAL("Unknown permanence.");
2750
2751                                 VK_CHECK(vkd.queueWaitIdle(queue));
2752                         }
2753                 }
2754
2755                 return tcu::TestStatus::pass("Pass");
2756         }
2757 #else
2758         DE_UNREF(context);
2759         DE_UNREF(config);
2760         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2761 #endif
2762 }
2763
2764 tcu::TestStatus testFenceFdDup2 (Context&                               context,
2765                                                                  const FenceTestConfig  config)
2766 {
2767 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2768         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2769         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2770         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2771         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2772         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2773         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2774
2775         checkFenceSupport(vki, physicalDevice, config.externalType);
2776
2777         {
2778                 const vk::VkFenceImportFlags    flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2779                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2780                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2781                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2782                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2783
2784                 TestLog&                                                log             = context.getTestContext().getLog();
2785                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2786                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2787
2788                 {
2789                         NativeHandle            fd, secondFd;
2790
2791                         if (transference == TRANSFERENCE_COPY)
2792                         {
2793                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2794                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2795                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2796                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2797                         }
2798                         else
2799                         {
2800                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2801                                 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2802                         }
2803
2804                         int                                     newFd           (dup2(fd.getFd(), secondFd.getFd()));
2805
2806                         if (newFd < 0)
2807                                 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2808
2809                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2810
2811                         {
2812                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2813
2814                                 if (transference == TRANSFERENCE_COPY)
2815                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2816                                 else if (transference == TRANSFERENCE_REFERENCE)
2817                                 {
2818                                         submitEmptySignal(vkd, queue, *fenceA);
2819                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2820                                 }
2821                                 else
2822                                         DE_FATAL("Unknown permanence.");
2823
2824                                 VK_CHECK(vkd.queueWaitIdle(queue));
2825                         }
2826                 }
2827
2828                 return tcu::TestStatus::pass("Pass");
2829         }
2830 #else
2831         DE_UNREF(context);
2832         DE_UNREF(config);
2833         TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2834 #endif
2835 }
2836
2837 tcu::TestStatus testFenceFdDup3 (Context&                               context,
2838                                                                  const FenceTestConfig  config)
2839 {
2840 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2841         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2842         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2843         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2844         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2845         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2846         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2847
2848         checkFenceSupport(vki, physicalDevice, config.externalType);
2849
2850         {
2851                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2852                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2853                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2854                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2855
2856                 TestLog&                                                log             = context.getTestContext().getLog();
2857                 const vk::Unique<vk::VkFence>   fenceA  (createExportableFence(vkd, *device, config.externalType));
2858                 const vk::Unique<vk::VkFence>   fenceB  (createExportableFence(vkd, *device, config.externalType));
2859
2860                 {
2861                         NativeHandle                                    fd, secondFd;
2862
2863                         if (transference == TRANSFERENCE_COPY)
2864                         {
2865                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2866                                 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2867                                 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2868                                         return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2869                         }
2870                         else
2871                         {
2872                                 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2873                                 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2874                         }
2875
2876                         const vk::VkFenceImportFlags    flags           = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2877                         const int                                               newFd           (dup3(fd.getFd(), secondFd.getFd(), 0));
2878
2879                         if (newFd < 0)
2880                                 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2881
2882                         TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2883
2884                         {
2885                                 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2886
2887                                 if (transference == TRANSFERENCE_COPY)
2888                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2889                                 else if (transference == TRANSFERENCE_REFERENCE)
2890                                 {
2891                                         submitEmptySignal(vkd, queue, *fenceA);
2892                                         VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2893                                 }
2894                                 else
2895                                         DE_FATAL("Unknown permanence.");
2896
2897                                 VK_CHECK(vkd.queueWaitIdle(queue));
2898                         }
2899                 }
2900
2901                 return tcu::TestStatus::pass("Pass");
2902         }
2903 #else
2904         DE_UNREF(context);
2905         DE_UNREF(config);
2906         TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2907 #endif
2908 }
2909
2910 tcu::TestStatus testFenceFdSendOverSocket (Context&                                     context,
2911                                                                                    const FenceTestConfig        config)
2912 {
2913 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2914         const Transference                                      transference            (getHandelTypeTransferences(config.externalType));
2915         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
2916         const CustomInstance                            instance                        (createTestInstance(context, 0u, 0u, config.externalType));
2917         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
2918         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2919         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2920
2921         checkFenceSupport(vki, physicalDevice, config.externalType);
2922
2923         {
2924                 const vk::Unique<vk::VkDevice>  device  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2925                 const vk::DeviceDriver                  vkd             (vkp, instance, *device);
2926                 vk::SimpleAllocator                             alloc   (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2927                 const vk::VkQueue                               queue   (getQueue(vkd, *device, queueFamilyIndex));
2928
2929                 TestLog&                                                log             = context.getTestContext().getLog();
2930                 const vk::Unique<vk::VkFence>   fence   (createExportableFence(vkd, *device, config.externalType));
2931                 NativeHandle                                    fd;
2932
2933                 if (transference == TRANSFERENCE_COPY)
2934                 {
2935                         submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2936                         if (fd.getFd() == -1)
2937                                 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2938                 }
2939                 else
2940                         getFenceNative(vkd, *device, *fence, config.externalType, fd);
2941
2942                 {
2943                         int sv[2];
2944
2945                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2946                         {
2947                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2948                                 TCU_FAIL("Failed to create socket pair");
2949                         }
2950
2951                         {
2952                                 const NativeHandle      srcSocket       (sv[0]);
2953                                 const NativeHandle      dstSocket       (sv[1]);
2954                                 std::string                     sendData        ("deqp");
2955
2956                                 // Send FD
2957                                 {
2958                                         const int                       fdRaw   (fd.getFd());
2959                                         msghdr                          msg;
2960                                         cmsghdr*                        cmsg;
2961                                         char                            buffer[CMSG_SPACE(sizeof(int))];
2962                                         iovec                           iov             = { &sendData[0], sendData.length()};
2963
2964                                         deMemset(&msg, 0, sizeof(msg));
2965
2966                                         msg.msg_control         = buffer;
2967                                         msg.msg_controllen      = sizeof(buffer);
2968                                         msg.msg_iovlen          = 1;
2969                                         msg.msg_iov                     = &iov;
2970
2971                                         cmsg                            = CMSG_FIRSTHDR(&msg);
2972                                         cmsg->cmsg_level        = SOL_SOCKET;
2973                                         cmsg->cmsg_type         = SCM_RIGHTS;
2974                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
2975
2976                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2977                                         msg.msg_controllen = cmsg->cmsg_len;
2978
2979                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2980                                         {
2981                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2982                                                 TCU_FAIL("Failed to send fd over socket");
2983                                         }
2984                                 }
2985
2986                                 // Recv FD
2987                                 {
2988                                         msghdr                  msg;
2989                                         char                    buffer[CMSG_SPACE(sizeof(int))];
2990                                         std::string             recvData        (4, '\0');
2991                                         iovec                   iov                     = { &recvData[0], recvData.length() };
2992
2993                                         deMemset(&msg, 0, sizeof(msg));
2994
2995                                         msg.msg_control         = buffer;
2996                                         msg.msg_controllen      = sizeof(buffer);
2997                                         msg.msg_iovlen          = 1;
2998                                         msg.msg_iov                     = &iov;
2999
3000                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3001
3002                                         if (bytes < 0)
3003                                         {
3004                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3005                                                 TCU_FAIL("Failed to recv fd over socket");
3006
3007                                         }
3008                                         else if (bytes != (ssize_t)sendData.length())
3009                                         {
3010                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3011                                         }
3012                                         else
3013                                         {
3014                                                 const vk::VkFenceImportFlags            flags   = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3015                                                 const cmsghdr* const                            cmsg    = CMSG_FIRSTHDR(&msg);
3016                                                 int                                                                     newFd_;
3017                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3018                                                 NativeHandle                                            newFd   (newFd_);
3019
3020                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3021                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3022                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3023                                                 TCU_CHECK(recvData == sendData);
3024                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3025
3026                                                 {
3027                                                         const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3028
3029                                                         if (transference == TRANSFERENCE_COPY)
3030                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3031                                                         else if (transference == TRANSFERENCE_REFERENCE)
3032                                                         {
3033                                                                 submitEmptySignal(vkd, queue, *newFence);
3034                                                                 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3035                                                         }
3036                                                         else
3037                                                                 DE_FATAL("Unknown permanence.");
3038
3039                                                         VK_CHECK(vkd.queueWaitIdle(queue));
3040                                                 }
3041                                         }
3042                                 }
3043                         }
3044                 }
3045         }
3046
3047         return tcu::TestStatus::pass("Pass");
3048 #else
3049         DE_UNREF(context);
3050         DE_UNREF(config);
3051         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3052 #endif
3053 }
3054
3055 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3056 {
3057         const vk::VkBufferCreateFlags           createFlags[]           =
3058         {
3059                 0u,
3060                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3061                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3062                 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3063         };
3064         const vk::VkBufferUsageFlags            usageFlags[]            =
3065         {
3066                 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3067                 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3068                 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3069                 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3070                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3071                 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3072                 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3073                 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3074                 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3075         };
3076         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3077         const CustomInstance                            instance                        (createTestInstance(context, 0u, externalType, 0u));
3078         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3079         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3080         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3081         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3082
3083         // VkDevice is only created if physical device claims to support any of these types.
3084         vk::Move<vk::VkDevice>                          device;
3085         de::MovePtr<vk::DeviceDriver>           vkd;
3086         bool                                                            deviceHasDedicated      = false;
3087
3088         TestLog&                                                        log                                     = context.getTestContext().getLog();
3089
3090         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3091         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3092         {
3093                 const vk::VkBufferViewCreateFlags                               createFlag              = createFlags[createFlagNdx];
3094                 const vk::VkBufferUsageFlags                                    usageFlag               = usageFlags[usageFlagNdx];
3095                 const vk::VkPhysicalDeviceExternalBufferInfo    info                    =
3096                 {
3097                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3098                         DE_NULL,
3099                         createFlag,
3100                         usageFlag,
3101                         externalType
3102                 };
3103                 vk::VkExternalBufferProperties                                  properties              =
3104                 {
3105                         vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3106                         DE_NULL,
3107                         { 0u, 0u, 0u }
3108                 };
3109
3110                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3111                         (deviceFeatures.sparseBinding == VK_FALSE))
3112                         continue;
3113
3114                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3115                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3116                         continue;
3117
3118                 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3119                         (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3120                         continue;
3121
3122                 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3123
3124                 log << TestLog::Message << properties << TestLog::EndMessage;
3125
3126                 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3127                 TCU_CHECK(properties.pNext == DE_NULL);
3128                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3129
3130                 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3131                 {
3132                         const bool      requiresDedicated       = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3133
3134                         if (!device || (requiresDedicated && !deviceHasDedicated))
3135                         {
3136                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3137                                 try
3138                                 {
3139                                         device                          = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3140                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3141                                         deviceHasDedicated      = requiresDedicated;
3142                                 }
3143                                 catch (const tcu::NotSupportedError& e)
3144                                 {
3145                                         log << e;
3146                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3147                                 }
3148                         }
3149                 }
3150
3151                 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3152                 {
3153                         DE_ASSERT(!!device);
3154                         DE_ASSERT(vkd);
3155
3156                         if (deviceHasDedicated)
3157                         {
3158                                 const vk::Unique<vk::VkBuffer>                          buffer                                          (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3159                                 const vk::VkMemoryDedicatedRequirements         reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3160                                 const bool                                                                      propertiesRequiresDedicated     = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3161                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
3162
3163                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
3164                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3165                         }
3166                         else
3167                         {
3168                                 // We can't query whether dedicated memory is required or not on per-object basis.
3169                                 // This check should be redundant as the code above tries to create device with
3170                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3171                                 // is required. However, checking again doesn't hurt.
3172                                 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3173                         }
3174                 }
3175         }
3176
3177         return tcu::TestStatus::pass("Pass");
3178 }
3179
3180 struct MemoryTestConfig
3181 {
3182                                                                                                 MemoryTestConfig        (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3183                                                                                                                                          bool                                                                           hostVisible_,
3184                                                                                                                                          bool                                                                           dedicated_)
3185                 : externalType  (externalType_)
3186                 , hostVisible   (hostVisible_)
3187                 , dedicated             (dedicated_)
3188         {
3189         }
3190
3191         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
3192         bool                                                                    hostVisible;
3193         bool                                                                    dedicated;
3194 };
3195
3196 #if (DE_OS == DE_OS_WIN32)
3197 deUint32 chooseWin32MemoryType(deUint32 bits)
3198 {
3199         if (bits == 0)
3200                 TCU_THROW(NotSupportedError, "No compatible memory type found");
3201
3202         return deCtz32(bits);
3203 }
3204 #endif
3205
3206 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3207 {
3208 #if (DE_OS == DE_OS_WIN32)
3209         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
3210         const CustomInstance                                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3211         const vk::InstanceDriver&                                       vki                                     (instance.getDriver());
3212         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3213         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3214         const vk::Unique<vk::VkDevice>                          device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3215         const vk::DeviceDriver                                          vkd                                     (vkp, instance, *device);
3216         const vk::VkBufferUsageFlags                            usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3217         const deUint32                                                          seed                            = 1261033864u;
3218         const vk::VkDeviceSize                                          bufferSize                      = 1024;
3219         const std::vector<deUint8>                                      testData                        (genTestData(seed, (size_t)bufferSize));
3220
3221         const vk::VkPhysicalDeviceMemoryProperties      memoryProps                     = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3222         const deUint32                                                          compatibleMemTypes      = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3223
3224         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3225
3226         // \note Buffer is only allocated to get memory requirements
3227         const vk::Unique<vk::VkBuffer>                          buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3228         const vk::VkMemoryRequirements                          requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3229         const vk::VkExportMemoryWin32HandleInfoKHR      win32Info                               =
3230         {
3231                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3232                 DE_NULL,
3233
3234                 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3235                 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3236                 (vk::pt::Win32LPCWSTR)DE_NULL
3237         };
3238         const vk::VkExportMemoryAllocateInfo            exportInfo                      =
3239         {
3240                 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3241                 &win32Info,
3242                 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
3243         };
3244
3245         const deUint32                                                          exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3246         const vk::VkMemoryAllocateInfo                          info                                    =
3247         {
3248                 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3249                 &exportInfo,
3250                 requirements.size,
3251                 exportedMemoryTypeIndex
3252         };
3253         const vk::Unique<vk::VkDeviceMemory>            memory                                  (vk::allocateMemory(vkd, *device, &info));
3254         NativeHandle                                                            handleA;
3255
3256         if (config.hostVisible)
3257                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3258
3259         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3260
3261         {
3262                 const vk::Unique<vk::VkDeviceMemory>    memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3263
3264                 if (config.hostVisible)
3265                 {
3266                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3267                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3268
3269                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3270                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testData[0]);
3271
3272                         writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3273                         writeHostMemory(vkd, *device, *memory,  testDataA.size(), &testDataB[0]);
3274
3275                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3276                         checkHostMemory(vkd, *device, *memory,  testData.size(), &testDataB[0]);
3277                 }
3278         }
3279
3280         return tcu::TestStatus::pass("Pass");
3281 #else
3282         DE_UNREF(context);
3283         DE_UNREF(config);
3284         TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3285 #endif
3286 }
3287
3288 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3289 {
3290         if (hostVisible)
3291         {
3292                 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3293                 return chooseHostVisibleMemoryType(memoryBits, properties);
3294         }
3295
3296         return chooseMemoryType(memoryBits);
3297 }
3298
3299 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3300 {
3301         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3302         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3303         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3304         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3305         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3306         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3307         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3308         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3309         const deUint32                                                  seed                            = 1261033864u;
3310         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3311         const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
3312
3313         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3314
3315         // \note Buffer is only allocated to get memory requirements
3316         const vk::Unique<vk::VkBuffer>                          buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3317         const vk::VkMemoryRequirements                          requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3318         const deUint32                                                          exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3319         const vk::Unique<vk::VkDeviceMemory>            memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3320         NativeHandle                                                            handleA;
3321
3322         if (config.hostVisible)
3323                 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3324
3325         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3326
3327         {
3328                 const vk::Unique<vk::VkBuffer>                  bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3329                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3330                 NativeHandle                                                    handleB (handleA);
3331                 const vk::Unique<vk::VkDeviceMemory>    memoryA (config.dedicated
3332                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3333                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3334                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3335                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3336                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3337
3338                 if (config.hostVisible)
3339                 {
3340                         const std::vector<deUint8>              testDataA               (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3341                         const std::vector<deUint8>              testDataB               (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3342
3343                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3344                         checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3345
3346                         writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3347                         writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3348
3349                         checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3350                         checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3351                 }
3352         }
3353
3354         return tcu::TestStatus::pass("Pass");
3355 }
3356
3357 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3358 {
3359         const size_t                                                    count                           = 4 * 1024;
3360         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3361         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3362         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3363         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3364         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3365         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3366         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3367         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3368         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3369
3370         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3371
3372         // \note Buffer is only allocated to get memory requirements
3373         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3374         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3375         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3376         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3377         NativeHandle                                                    handleA;
3378
3379         getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3380
3381         for (size_t ndx = 0; ndx < count; ndx++)
3382         {
3383                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3384                 NativeHandle                                                    handleB (handleA);
3385                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3386                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3387                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3388         }
3389
3390         return tcu::TestStatus::pass("Pass");
3391 }
3392
3393 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3394 {
3395         const size_t                                                    count                           = 4 * 1024;
3396         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3397         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3398         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3399         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3400         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3401         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3402         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3403         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3404         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3405
3406         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3407
3408         // \note Buffer is only allocated to get memory requirements
3409         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3410         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3411         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3412         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3413
3414         for (size_t ndx = 0; ndx < count; ndx++)
3415         {
3416                 NativeHandle    handle;
3417                 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3418         }
3419
3420         return tcu::TestStatus::pass("Pass");
3421 }
3422
3423 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3424 {
3425         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3426         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3427         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3428         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3429         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3430         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3431         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3432         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3433         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3434
3435         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3436
3437         // \note Buffer is only allocated to get memory requirements
3438         const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3439         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3440         const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3441         const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3442
3443         vk::VkMemoryFdPropertiesKHR     properties;
3444         NativeHandle                            handle;
3445
3446         getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3447         properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3448         vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3449
3450         switch (config.externalType)
3451         {
3452                 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3453                         TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3454                         break;
3455                 default:
3456                         // Invalid external memory type for this test.
3457                         DE_ASSERT(false);
3458                         break;
3459         }
3460
3461         return tcu::TestStatus::pass("Pass");
3462 }
3463
3464 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3465 {
3466 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3467         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3468         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3469         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3470         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3471         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3472
3473         {
3474                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3475                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3476
3477                 TestLog&                                                                log                             = context.getTestContext().getLog();
3478                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3479                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3480                 const deUint32                                                  seed                    = 851493858u;
3481                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3482
3483                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3484
3485                 // \note Buffer is only allocated to get memory requirements
3486                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3487                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3488                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3489                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3490
3491                 if (config.hostVisible)
3492                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3493
3494                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3495                 NativeHandle                                                    newFd                   (dup(fd.getFd()));
3496
3497                 if (newFd.getFd() < 0)
3498                         log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3499
3500                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3501
3502                 {
3503                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3504                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3505                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3506                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3507
3508                         if (config.hostVisible)
3509                         {
3510                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3511
3512                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3513
3514                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3515                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3516                         }
3517                 }
3518
3519                 return tcu::TestStatus::pass("Pass");
3520         }
3521 #else
3522         DE_UNREF(context);
3523         DE_UNREF(config);
3524         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3525 #endif
3526 }
3527
3528 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3529 {
3530 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3531         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3532         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3533         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3534         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3535         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3536
3537         {
3538                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3539                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3540
3541                 TestLog&                                                                log                             = context.getTestContext().getLog();
3542                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3543                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3544                 const deUint32                                                  seed                    = 224466865u;
3545                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3546
3547                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3548
3549                 // \note Buffer is only allocated to get memory requirements
3550                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3551                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3552                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3553                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3554
3555                 if (config.hostVisible)
3556                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3557
3558                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3559                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
3560                 const int                                                               newFd                   (dup2(fd.getFd(), secondFd.getFd()));
3561
3562                 if (newFd < 0)
3563                         log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3564
3565                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3566
3567                 {
3568                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3569                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3570                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3571                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3572
3573                         if (config.hostVisible)
3574                         {
3575                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3576
3577                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3578
3579                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3580                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3581                         }
3582                 }
3583
3584                 return tcu::TestStatus::pass("Pass");
3585         }
3586 #else
3587         DE_UNREF(context);
3588         DE_UNREF(config);
3589         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3590 #endif
3591 }
3592
3593 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3594 {
3595 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3596         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3597         const CustomInstance                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3598         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3599         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3600         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3601
3602         {
3603                 const vk::Unique<vk::VkDevice>                  device                  (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3604                 const vk::DeviceDriver                                  vkd                             (vkp, instance, *device);
3605
3606                 TestLog&                                                                log                             = context.getTestContext().getLog();
3607                 const vk::VkBufferUsageFlags                    usage                   = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3608                 const vk::VkDeviceSize                                  bufferSize              = 1024;
3609                 const deUint32                                                  seed                    = 2554088961u;
3610                 const std::vector<deUint8>                              testData                (genTestData(seed, (size_t)bufferSize));
3611
3612                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3613
3614                 // \note Buffer is only allocated to get memory requirements
3615                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3616                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3617                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3618                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3619
3620                 if (config.hostVisible)
3621                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3622
3623                 const NativeHandle                                              fd                              (getMemoryFd(vkd, *device, *memory, config.externalType));
3624                 NativeHandle                                                    secondFd                (getMemoryFd(vkd, *device, *memory, config.externalType));
3625                 const int                                                               newFd                   (dup3(fd.getFd(), secondFd.getFd(), 0));
3626
3627                 if (newFd < 0)
3628                         log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3629
3630                 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3631
3632                 {
3633                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3634                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3635                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3636                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3637
3638                         if (config.hostVisible)
3639                         {
3640                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3641
3642                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3643
3644                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3645                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3646                         }
3647                 }
3648
3649                 return tcu::TestStatus::pass("Pass");
3650         }
3651 #else
3652         DE_UNREF(context);
3653         DE_UNREF(config);
3654         TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3655 #endif
3656 }
3657
3658 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3659 {
3660 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3661         const vk::PlatformInterface&                            vkp                                     (context.getPlatformInterface());
3662         const CustomInstance                                            instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3663         const vk::InstanceDriver&                                       vki                                     (instance.getDriver());
3664         const vk::VkPhysicalDevice                                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3665         const deUint32                                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3666
3667         {
3668                 const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3669                 const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3670
3671                 TestLog&                                                                log                                     = context.getTestContext().getLog();
3672                 const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3673                 const vk::VkDeviceSize                                  bufferSize                      = 1024;
3674                 const deUint32                                                  seed                            = 3403586456u;
3675                 const std::vector<deUint8>                              testData                        (genTestData(seed, (size_t)bufferSize));
3676
3677                 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3678
3679                 // \note Buffer is only allocated to get memory requirements
3680                 const vk::Unique<vk::VkBuffer>                  buffer                                  (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3681                 const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *buffer));
3682                 const deUint32                                                  exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3683                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3684
3685                 if (config.hostVisible)
3686                         writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3687
3688                 const NativeHandle                                              fd                                      (getMemoryFd(vkd, *device, *memory, config.externalType));
3689
3690                 {
3691                         int sv[2];
3692
3693                         if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3694                         {
3695                                 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3696                                 TCU_FAIL("Failed to create socket pair");
3697                         }
3698
3699                         {
3700                                 const NativeHandle      srcSocket       (sv[0]);
3701                                 const NativeHandle      dstSocket       (sv[1]);
3702                                 std::string                     sendData        ("deqp");
3703
3704                                 // Send FD
3705                                 {
3706                                         const int                       fdRaw   (fd.getFd());
3707                                         msghdr                          msg;
3708                                         cmsghdr*                        cmsg;
3709                                         char                            tmpBuffer[CMSG_SPACE(sizeof(int))];
3710                                         iovec                           iov             = { &sendData[0], sendData.length()};
3711
3712                                         deMemset(&msg, 0, sizeof(msg));
3713
3714                                         msg.msg_control         = tmpBuffer;
3715                                         msg.msg_controllen      = sizeof(tmpBuffer);
3716                                         msg.msg_iovlen          = 1;
3717                                         msg.msg_iov                     = &iov;
3718
3719                                         cmsg                            = CMSG_FIRSTHDR(&msg);
3720                                         cmsg->cmsg_level        = SOL_SOCKET;
3721                                         cmsg->cmsg_type         = SCM_RIGHTS;
3722                                         cmsg->cmsg_len          = CMSG_LEN(sizeof(int));
3723
3724                                         deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3725                                         msg.msg_controllen = cmsg->cmsg_len;
3726
3727                                         if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3728                                         {
3729                                                 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3730                                                 TCU_FAIL("Failed to send fd over socket");
3731                                         }
3732                                 }
3733
3734                                 // Recv FD
3735                                 {
3736                                         msghdr                  msg;
3737                                         char                    tmpBuffer[CMSG_SPACE(sizeof(int))];
3738                                         std::string             recvData        (4, '\0');
3739                                         iovec                   iov                     = { &recvData[0], recvData.length() };
3740
3741                                         deMemset(&msg, 0, sizeof(msg));
3742
3743                                         msg.msg_control         = tmpBuffer;
3744                                         msg.msg_controllen      = sizeof(tmpBuffer);
3745                                         msg.msg_iovlen          = 1;
3746                                         msg.msg_iov                     = &iov;
3747
3748                                         const ssize_t   bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3749
3750                                         if (bytes < 0)
3751                                         {
3752                                                 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3753                                                 TCU_FAIL("Failed to recv fd over socket");
3754
3755                                         }
3756                                         else if (bytes != (ssize_t)sendData.length())
3757                                         {
3758                                                 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3759                                         }
3760                                         else
3761                                         {
3762                                                 const cmsghdr* const    cmsg    = CMSG_FIRSTHDR(&msg);
3763                                                 int                                             newFd_;
3764                                                 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3765                                                 NativeHandle                    newFd   (newFd_);
3766
3767                                                 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3768                                                 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3769                                                 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3770                                                 TCU_CHECK(recvData == sendData);
3771                                                 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3772
3773                                                 {
3774                                                         const vk::Unique<vk::VkBuffer>                  newBuffer       (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3775                                                         const vk::Unique<vk::VkDeviceMemory>    newMemory       (config.dedicated
3776                                                                                                                                                                  ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3777                                                                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3778
3779                                                         if (config.hostVisible)
3780                                                         {
3781                                                                 const std::vector<deUint8>      testDataA       (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3782
3783                                                                 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3784
3785                                                                 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3786                                                                 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3787                                                         }
3788                                                 }
3789                                         }
3790                                 }
3791                         }
3792                 }
3793         }
3794
3795         return tcu::TestStatus::pass("Pass");
3796 #else
3797         DE_UNREF(context);
3798         DE_UNREF(config);
3799         TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3800 #endif
3801 }
3802
3803 struct BufferTestConfig
3804 {
3805                                                                                         BufferTestConfig        (vk::VkExternalMemoryHandleTypeFlagBits         externalType_,
3806                                                                                                                                  bool                                                                           dedicated_)
3807                 : externalType  (externalType_)
3808                 , dedicated             (dedicated_)
3809         {
3810         }
3811
3812         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
3813         bool                                                                    dedicated;
3814 };
3815
3816 tcu::TestStatus testBufferBindExportImportBind (Context&                                context,
3817                                                                                                 const BufferTestConfig  config)
3818 {
3819         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3820         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3821         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3822         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3823         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3824         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3825         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3826         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3827         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3828
3829         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3830
3831         // \note Buffer is only allocated to get memory requirements
3832         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3833         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3834         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3835         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3836         NativeHandle                                                    handle;
3837
3838         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3839
3840         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3841
3842         {
3843                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3844                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3845                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3846                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3847
3848                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3849         }
3850
3851         return tcu::TestStatus::pass("Pass");
3852 }
3853
3854 tcu::TestStatus testBufferExportBindImportBind (Context&                                context,
3855                                                                                                 const BufferTestConfig  config)
3856 {
3857         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3858         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3859         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3860         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3861         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3862         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3863         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3864         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3865         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3866
3867         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3868
3869         // \note Buffer is only allocated to get memory requirements
3870         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3871         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3872         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3873         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3874         NativeHandle                                                    handle;
3875
3876         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3877         VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3878
3879         {
3880                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3881                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3882                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3883                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3884
3885                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3886         }
3887
3888         return tcu::TestStatus::pass("Pass");
3889 }
3890
3891 tcu::TestStatus testBufferExportImportBindBind (Context&                                context,
3892                                                                                                 const BufferTestConfig  config)
3893 {
3894         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
3895         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
3896         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
3897         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3898         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3899         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3900         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
3901         const vk::VkBufferUsageFlags                    usage                           = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3902         const vk::VkDeviceSize                                  bufferSize                      = 1024;
3903
3904         checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3905
3906         // \note Buffer is only allocated to get memory requirements
3907         const vk::Unique<vk::VkBuffer>                  bufferA                                 (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3908         const vk::VkMemoryRequirements                  requirements                    (getBufferMemoryRequirements(vkd, *device, *bufferA));
3909         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3910         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3911         NativeHandle                                                    handle;
3912
3913         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3914
3915         {
3916                 const vk::Unique<vk::VkBuffer>                  bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3917                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
3918                                                                                                                  ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3919                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3920
3921                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3922                 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3923         }
3924
3925         return tcu::TestStatus::pass("Pass");
3926 }
3927
3928 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3929 {
3930         const vk::VkImageCreateFlags            createFlags[]           =
3931         {
3932                 0u,
3933                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3934                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3935                 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3936                 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3937                 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3938         };
3939         const vk::VkImageUsageFlags                     usageFlags[]            =
3940         {
3941                 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3942                 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3943                 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3944                 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3945                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3946                 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3947                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3948                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3949                 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3950                 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3951         };
3952         const vk::PlatformInterface&            vkp                                     (context.getPlatformInterface());
3953         const CustomInstance                            instance                        (createTestInstance(context, 0u, externalType, 0u));
3954         const vk::InstanceDriver&                       vki                                     (instance.getDriver());
3955         const vk::VkPhysicalDevice                      physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3956         const vk::VkPhysicalDeviceFeatures      deviceFeatures          (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3957         const deUint32                                          queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3958
3959         // VkDevice is only created if physical device claims to support any of these types.
3960         vk::Move<vk::VkDevice>                          device;
3961         de::MovePtr<vk::DeviceDriver>           vkd;
3962         bool                                                            deviceHasDedicated      = false;
3963
3964         TestLog&                                                        log                                     = context.getTestContext().getLog();
3965
3966         for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3967         for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3968         {
3969                 const vk::VkImageViewCreateFlags                                                createFlag              = createFlags[createFlagNdx];
3970                 const vk::VkImageUsageFlags                                                             usageFlag               = usageFlags[usageFlagNdx];
3971                 const vk::VkFormat                                                                              format                  =
3972                                 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3973                 const vk::VkImageType                                                                   type                    = vk::VK_IMAGE_TYPE_2D;
3974                 const vk::VkImageTiling                                                                 tiling                  = vk::VK_IMAGE_TILING_OPTIMAL;
3975                 const vk::VkPhysicalDeviceExternalImageFormatInfo               externalInfo    =
3976                 {
3977                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3978                         DE_NULL,
3979                         externalType
3980                 };
3981                 const vk::VkPhysicalDeviceImageFormatInfo2                              info                    =
3982                 {
3983                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3984                         &externalInfo,
3985
3986                         format,
3987                         type,
3988                         tiling,
3989                         usageFlag,
3990                         createFlag,
3991                 };
3992                 vk::VkExternalImageFormatProperties                                             externalProperties      =
3993                 {
3994                         vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3995                         DE_NULL,
3996                         { 0u, 0u, 0u }
3997                 };
3998                 vk::VkImageFormatProperties2                                                    properties                      =
3999                 {
4000                         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4001                         &externalProperties,
4002                         {
4003                                 { 0u, 0u, 0u },
4004                                 0u,
4005                                 0u,
4006                                 0u,
4007                                 0u
4008                         }
4009                 };
4010
4011                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4012                         (deviceFeatures.sparseBinding == VK_FALSE))
4013                         continue;
4014
4015                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4016                         (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4017                         continue;
4018
4019                 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4020                         (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4021                         continue;
4022
4023                 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4024                         continue;
4025                 }
4026
4027                 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4028                 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4029                 TCU_CHECK(externalProperties.pNext == DE_NULL);
4030                 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4031
4032                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4033                 {
4034                         const bool      requiresDedicated       = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4035
4036                         if (!device || (requiresDedicated && !deviceHasDedicated))
4037                         {
4038                                 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4039                                 try
4040                                 {
4041                                         device                          = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4042                                         vkd                                     = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4043                                         deviceHasDedicated      = requiresDedicated;
4044                                 }
4045                                 catch (const tcu::NotSupportedError& e)
4046                                 {
4047                                         log << e;
4048                                         TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4049                                 }
4050                         }
4051                 }
4052
4053                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4054                 {
4055                         DE_ASSERT(!!device);
4056                         DE_ASSERT(vkd);
4057
4058                         if (deviceHasDedicated)
4059                         {
4060                                 // Memory requirements cannot be queried without binding the image.
4061                                 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4062                                         continue;
4063
4064                                 const vk::Unique<vk::VkImage>                           image                                           (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4065                                 const vk::VkMemoryDedicatedRequirements         reqs                                            (getMemoryDedicatedRequirements(*vkd, *device, *image));
4066                                 const bool                                                                      propertiesRequiresDedicated     = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4067                                 const bool                                                                      objectRequiresDedicated         = (reqs.requiresDedicatedAllocation != VK_FALSE);
4068
4069                                 if (propertiesRequiresDedicated != objectRequiresDedicated)
4070                                         TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4071                         }
4072                         else
4073                         {
4074                                 // We can't query whether dedicated memory is required or not on per-object basis.
4075                                 // This check should be redundant as the code above tries to create device with
4076                                 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4077                                 // is required. However, checking again doesn't hurt.
4078                                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4079                         }
4080                 }
4081         }
4082
4083         return tcu::TestStatus::pass("Pass");
4084 }
4085
4086 struct ImageTestConfig
4087 {
4088                                                                                         ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits         externalType_,
4089                                                                                                                          bool                                                                           dedicated_)
4090                 : externalType  (externalType_)
4091                 , dedicated             (dedicated_)
4092         {
4093         }
4094
4095         vk::VkExternalMemoryHandleTypeFlagBits  externalType;
4096         bool                                                                    dedicated;
4097 };
4098
4099 tcu::TestStatus testImageBindExportImportBind (Context&                                 context,
4100                                                                                            const ImageTestConfig        config)
4101 {
4102         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4103         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4104         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4105         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4106         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4107         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4108         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4109         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);
4110         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4111         const deUint32                                                  width                           = 64u;
4112         const deUint32                                                  height                          = 64u;
4113         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4114
4115         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4116
4117         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4118         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4119         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4120         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4121         NativeHandle                                                    handle;
4122
4123         VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4124
4125         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4126
4127         {
4128                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4129                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4130                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4131                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4132                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4133
4134                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4135         }
4136
4137         return tcu::TestStatus::pass("Pass");
4138 }
4139
4140 tcu::TestStatus testImageExportBindImportBind (Context&                                 context,
4141                                                                                            const ImageTestConfig        config)
4142 {
4143         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4144         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4145         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4146         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4147         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4148         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4149         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4150         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);
4151         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4152         const deUint32                                                  width                           = 64u;
4153         const deUint32                                                  height                          = 64u;
4154         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4155
4156         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4157
4158         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4159         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4160         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4161         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4162         NativeHandle                                                    handle;
4163
4164         if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4165         {
4166                 // AHB required the image memory to be bound first.
4167                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4168                 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4169         }
4170         else
4171         {
4172                 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4173                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4174         }
4175
4176         {
4177                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4178                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4179                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4180                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4181                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4182
4183                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4184         }
4185
4186         return tcu::TestStatus::pass("Pass");
4187 }
4188
4189 tcu::TestStatus testImageExportImportBindBind (Context&                                 context,
4190                                                                                            const ImageTestConfig        config)
4191 {
4192         const vk::PlatformInterface&                    vkp                                     (context.getPlatformInterface());
4193         const CustomInstance                                    instance                        (createTestInstance(context, 0u, config.externalType, 0u));
4194         const vk::InstanceDriver&                               vki                                     (instance.getDriver());
4195         const vk::VkPhysicalDevice                              physicalDevice          (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4196         const deUint32                                                  queueFamilyIndex        (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4197         const vk::Unique<vk::VkDevice>                  device                          (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4198         const vk::DeviceDriver                                  vkd                                     (vkp, instance, *device);
4199         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);
4200         const vk::VkFormat                                              format                          = vk::VK_FORMAT_R8G8B8A8_UNORM;
4201         const deUint32                                                  width                           = 64u;
4202         const deUint32                                                  height                          = 64u;
4203         const vk::VkImageTiling                                 tiling                          = vk::VK_IMAGE_TILING_OPTIMAL;
4204
4205         checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4206
4207         if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4208         {
4209                 // AHB required the image memory to be bound first, which is not possible in this test.
4210                 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4211         }
4212
4213         // \note Image is only allocated to get memory requirements
4214         const vk::Unique<vk::VkImage>                   imageA                                  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4215         const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4216         const deUint32                                                  exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4217         const vk::Unique<vk::VkDeviceMemory>    memoryA                                 (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4218         NativeHandle                                                    handle;
4219
4220         getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4221
4222         {
4223                 const vk::Unique<vk::VkImage>                   imageB  (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4224                 const deUint32                                                  idx             = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4225                 const vk::Unique<vk::VkDeviceMemory>    memoryB (config.dedicated
4226                                                                                                                  ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4227                                                                                                                  : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4228
4229                 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4230                 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4231         }
4232
4233         return tcu::TestStatus::pass("Pass");
4234 }
4235
4236 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4237 {
4238         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4239                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4240 }
4241
4242 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4243 {
4244         const Transference transference (getHandelTypeTransferences(config.externalType));
4245         if (transference == TRANSFERENCE_COPY)
4246                 checkEvent(context, config);
4247 }
4248
4249 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4250 {
4251         const struct
4252         {
4253                 const char* const       name;
4254                 const Permanence        permanence;
4255         } permanences[] =
4256         {
4257                 { "temporary", PERMANENCE_TEMPORARY     },
4258                 { "permanent", PERMANENCE_PERMANENT     }
4259         };
4260
4261         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4262
4263         addFunctionCase(fenceGroup.get(), "info",       "Test external fence queries.", testFenceQueries,       externalType);
4264
4265         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4266         {
4267                 const Permanence                permanence              (permanences[permanenceNdx].permanence);
4268                 const char* const               permanenceName  (permanences[permanenceNdx].name);
4269                 const FenceTestConfig   config                  (externalType, permanence);
4270
4271                 if (!isSupportedPermanence(externalType, permanence))
4272                         continue;
4273
4274                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4275                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4276                 {
4277                         addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName,        "Test creating fence with win32 properties.",   testFenceWin32Create,   config);
4278                 }
4279
4280                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName,                            "Test importing fence twice.",                                                                                  checkSupport,   initProgramsToGetNativeFd,      testFenceImportTwice,                           config);
4281                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName,                                        "Test importing again over previously imported fence.",                                 checkSupport,   initProgramsToGetNativeFd,      testFenceImportReimport,                        config);
4282                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,           "Test importing fence multiple times.",                                                                 checkSupport,   initProgramsToGetNativeFd,      testFenceMultipleImports,                       config);
4283                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,       "Test signaling, exporting, importing and waiting for the sempahore.",  checkEvent,             initProgramsToGetNativeFd,      testFenceSignalExportImportWait,        config);
4284                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName,                           "Test signaling and importing the fence.",                                                              checkSupport,   initProgramsToGetNativeFd,      testFenceSignalImport,                          config);
4285                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName,                                           "Test resetting the fence.",                                                                                    checkEvent,             initProgramsToGetNativeFd,      testFenceReset,                                         config);
4286                 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName,                            "Test fences transference.",                                                                                    checkEvent,             initProgramsToGetNativeFd,      testFenceTransference,                          config);
4287
4288                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4289                 {
4290                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName,                 "Test import signaled fence fd.",                                                                               initProgramsToGetNativeFd,      testFenceImportSyncFdSignaled,          config);
4291                 }
4292
4293                 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4294                         || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4295                 {
4296                         // \note Not supported on WIN32 handles
4297                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,   "Test exporting fence multiple times.",         checkSupport,   initProgramsToGetNativeFd,      testFenceMultipleExports,       config);
4298
4299                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName,                                             "Test calling dup() on exported fence.",        checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup,                         config);
4300                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName,                                    "Test calling dup2() on exported fence.",       checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup2,                        config);
4301                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName,                                    "Test calling dup3() on exported fence.",       checkSupport,   initProgramsToGetNativeFd,      testFenceFdDup3,                        config);
4302                         addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,                "Test sending fence fd over socket.",           checkSupport,   initProgramsToGetNativeFd,      testFenceFdSendOverSocket,      config);
4303                 }
4304
4305                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4306                 {
4307                         addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,                  "Test signaling and then waiting for the the sepmahore.",                       testFenceSignalWaitImport,                      config);
4308                         addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,   "Test exporting, signaling, importing and waiting for the fence.",      testFenceExportSignalImportWait,        config);
4309                         addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,   "Test exporting, importing, signaling and waiting for the fence.",      testFenceExportImportSignalWait,        config);
4310                 }
4311         }
4312
4313         return fenceGroup;
4314 }
4315
4316 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4317 {
4318         DE_UNREF(createFlag);
4319
4320         AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4321         if (!ahbApi)
4322         {
4323                 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4324         }
4325
4326 #if (DE_OS == DE_OS_ANDROID)
4327         // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4328         if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4329                 return false;
4330 #endif
4331
4332         vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4333         if (ahb.internal == DE_NULL)
4334         {
4335                 enableMaxLayerTest = false;
4336                 // try again with layerCount '1'
4337                 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4338                 if (ahb.internal == DE_NULL)
4339                 {
4340                         return false;
4341                 }
4342         }
4343         NativeHandle nativeHandle(ahb);
4344
4345         const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4346         const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4347
4348         for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4349         {
4350                 // Both mappings should be equivalent and work.
4351                 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4352
4353                 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4354                 {
4355                         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4356                         DE_NULL,
4357                         vk::VK_FORMAT_UNDEFINED,
4358                         0u,
4359                         0u,
4360                         mapping,
4361                         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4362                         vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4363                         vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4364                         vk::VK_CHROMA_LOCATION_COSITED_EVEN
4365                 };
4366
4367                 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4368                 {
4369                         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4370                         &formatProperties,
4371                         0u,
4372                         0u
4373                 };
4374
4375                 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4376                 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4377                 TCU_CHECK(formatProperties.format == format);
4378                 TCU_CHECK(formatProperties.externalFormat != 0u);
4379                 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4380                 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4381         }
4382
4383         return true;
4384 }
4385
4386 tcu::TestStatus testAndroidHardwareBufferImageFormat  (Context& context, vk::VkFormat format)
4387 {
4388         AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4389         if (!ahbApi)
4390         {
4391                 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4392         }
4393
4394         const vk::VkExternalMemoryHandleTypeFlagBits  externalMemoryType  =     vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4395         const vk::PlatformInterface&                              vkp                                   (context.getPlatformInterface());
4396         const CustomInstance                                              instance                              (createTestInstance(context, 0u, externalMemoryType, 0u));
4397         const vk::InstanceDriver&                                         vki                                   (instance.getDriver());
4398         const vk::VkPhysicalDevice                                        physicalDevice                (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4399
4400         vk::VkPhysicalDeviceProtectedMemoryFeatures             protectedFeatures;
4401         protectedFeatures.sType                         = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4402         protectedFeatures.pNext                         = DE_NULL;
4403         protectedFeatures.protectedMemory       = VK_FALSE;
4404
4405         vk::VkPhysicalDeviceFeatures2                                   deviceFeatures;
4406         deviceFeatures.sType            = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4407         deviceFeatures.pNext            = &protectedFeatures;
4408
4409         vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4410
4411         const deUint32                                                            queueFamilyIndex              (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4412         const vk::Unique<vk::VkDevice>                            device                                (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4413         const vk::DeviceDriver                                            vkd                                   (vkp, instance, *device);
4414         TestLog&                                                                          log                             = context.getTestContext().getLog();
4415         const vk::VkPhysicalDeviceLimits                          limits                          = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4416
4417         const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4418                                                                                                                                                                                    : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4419
4420         const vk::VkImageUsageFlagBits                            usageFlags[]            =
4421         {
4422                 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4423                 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4424                 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4425                 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4426                 framebufferUsageFlag,
4427         };
4428         const vk::VkImageCreateFlagBits                           createFlags[]           =
4429         {
4430                 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4431                 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4432                 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4433                 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4434         };
4435         const vk::VkImageTiling                                           tilings[]                       =
4436         {
4437                 vk::VK_IMAGE_TILING_OPTIMAL,
4438                 vk::VK_IMAGE_TILING_LINEAR,
4439         };
4440         deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4441         const size_t    one                                                     = 1u;
4442         const size_t    numOfUsageFlags                         = DE_LENGTH_OF_ARRAY(usageFlags);
4443         const size_t    numOfCreateFlags                        = DE_LENGTH_OF_ARRAY(createFlags);
4444         const size_t    numOfFlagCombos                         = one << (numOfUsageFlags + numOfCreateFlags);
4445         const size_t    numOfTilings                            = DE_LENGTH_OF_ARRAY(tilings);
4446
4447         for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4448         {
4449                 vk::VkImageUsageFlags   usage                           = 0;
4450                 vk::VkImageCreateFlags  createFlag                      = 0;
4451                 deUint64                                requiredAhbUsage        = 0;
4452                 bool                                    enableMaxLayerTest      = true;
4453                 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4454                 {
4455                         if ((combo & (one << usageNdx)) == 0)
4456                                 continue;
4457                         usage |= usageFlags[usageNdx];
4458                         requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4459                 }
4460                 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4461                 {
4462                         const size_t    bit     = numOfUsageFlags + createFlagNdx;
4463                         if ((combo & (one << bit)) == 0)
4464                                 continue;
4465                         if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4466                                 (protectedFeatures.protectedMemory == VK_FALSE))
4467                                 continue;
4468
4469                         createFlag |= createFlags[createFlagNdx];
4470                         requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4471                 }
4472
4473                 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4474                 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4475                         continue;
4476
4477                 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4478                 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4479                         continue;
4480
4481                 bool foundAnyUsableTiling = false;
4482                 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4483                 {
4484                         const vk::VkImageTiling tiling = tilings[tilingIndex];
4485
4486                         const vk::VkPhysicalDeviceExternalImageFormatInfo       externalInfo            =
4487                         {
4488                                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4489                                 DE_NULL,
4490                                 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4491                         };
4492                         const vk::VkPhysicalDeviceImageFormatInfo2                      info                            =
4493                         {
4494                                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4495                                 &externalInfo,
4496                                 format,
4497                                 vk::VK_IMAGE_TYPE_2D,
4498                                 tiling,
4499                                 usage,
4500                                 createFlag,
4501                         };
4502
4503                         vk::VkAndroidHardwareBufferUsageANDROID                         ahbUsageProperties      =
4504                         {
4505                                 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4506                                 DE_NULL,
4507                                 0u
4508                         };
4509                         vk::VkExternalImageFormatProperties                                     externalProperties      =
4510                         {
4511                                 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4512                                 &ahbUsageProperties,
4513                                 { 0u, 0u, 0u }
4514                         };
4515                         vk::VkImageFormatProperties2                                            properties                      =
4516                         {
4517                                 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4518                                 &externalProperties,
4519                                 {
4520                                         { 0u, 0u, 0u },
4521                                         0u,
4522                                         0u,
4523                                         0u,
4524                                         0u
4525                                 }
4526                         };
4527
4528                         if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4529                         {
4530                                 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4531                                 continue;
4532                         }
4533
4534                         foundAnyUsableTiling = true;
4535
4536                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4537                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4538                         TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4539                         deUint32 maxWidth   = properties.imageFormatProperties.maxExtent.width;
4540                         deUint32 maxHeight  = properties.imageFormatProperties.maxExtent.height;
4541                         TCU_CHECK(maxWidth >= 4096);
4542                         TCU_CHECK(maxHeight >= 4096);
4543                         // Even if not requested, at least one of GPU_* usage flags must be present.
4544                         TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4545                         // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4546                         TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4547
4548                         log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4549                                 << TestLog::EndMessage;
4550
4551                         struct ImageSize
4552                         {
4553                                 deUint32 width;
4554                                 deUint32 height;
4555                         };
4556                         ImageSize sizes[] =
4557                         {
4558                                 {64u, 64u},
4559                                 {1024u, 2096u},
4560                         };
4561
4562                         deUint32 exportedMemoryTypeIndex = 0;
4563
4564                         if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4565                         {
4566                                 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4567
4568                                 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4569                                 {
4570                                         if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4571                                         {
4572                                                 exportedMemoryTypeIndex = memoryTypeIndex;
4573                                                 break;
4574                                         }
4575                                 }
4576                         }
4577
4578                         for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4579                         {
4580                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4581                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4582                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4583                                 NativeHandle                                                    handle;
4584
4585                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4586                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4587
4588                                 deUint32 ahbFormat = 0;
4589                                 deUint64 anhUsage  = 0;
4590                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4591                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4592                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4593
4594                                 // Let watchdog know we're alive
4595                                 context.getTestContext().touchWatchdog();
4596                         }
4597
4598                         if (properties.imageFormatProperties.maxMipLevels >= 7u)
4599                         {
4600                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4601                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4602                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4603                                 NativeHandle                                                    handle;
4604
4605                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4606                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4607
4608                                 deUint32 ahbFormat = 0;
4609                                 deUint64 anhUsage  = 0;
4610                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4611                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4612                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4613                         }
4614
4615                         if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4616                         {
4617                                 const vk::Unique<vk::VkImage>                   image                                   (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4618                                 const vk::VkMemoryRequirements                  requirements                    (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4619                                 const vk::Unique<vk::VkDeviceMemory>    memory                                  (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4620                                 NativeHandle                                                    handle;
4621
4622                                 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4623                                 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4624
4625                                 deUint32 ahbFormat = 0;
4626                                 deUint64 anhUsage  = 0;
4627                                 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4628                                 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4629                                 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4630                         }
4631                 }
4632
4633                 TCU_CHECK(foundAnyUsableTiling);
4634         }
4635         return tcu::TestStatus::pass("Pass");
4636 }
4637
4638 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4639 {
4640         de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4641
4642         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4643         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4644         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4645         fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4646
4647         return fenceGroup;
4648 }
4649
4650 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4651 {
4652         const struct
4653         {
4654                 const char* const       name;
4655                 const Permanence        permanence;
4656         } permanences[] =
4657         {
4658                 { "temporary", PERMANENCE_TEMPORARY     },
4659                 { "permanent", PERMANENCE_PERMANENT     }
4660         };
4661         const struct
4662         {
4663                 const char* const       name;
4664                 vk::VkSemaphoreType     type;
4665         } semaphoreTypes[] =
4666         {
4667                 { "binary",             vk::VK_SEMAPHORE_TYPE_BINARY },
4668                 { "timeline",   vk::VK_SEMAPHORE_TYPE_TIMELINE },
4669         };
4670
4671         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4672
4673         for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4674         {
4675                 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4676                                                 "Test external semaphore queries.",     testSemaphoreQueries,
4677                                                 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4678         }
4679
4680         for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4681         {
4682                 const Permanence                        permanence              (permanences[permanenceNdx].permanence);
4683                 const char* const                       permanenceName  (permanences[permanenceNdx].name);
4684                 const SemaphoreTestConfig       config                  (externalType, permanence);
4685
4686                 if (!isSupportedPermanence(externalType, permanence))
4687                         continue;
4688
4689                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4690                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4691                 {
4692                         addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,    "Test creating semaphore with win32 properties.",       testSemaphoreWin32Create,       config);
4693                 }
4694
4695                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName,                                "Test importing semaphore twice.",                                                                              checkSupport,   initProgramsToGetNativeFd,      testSemaphoreImportTwice,                               config);
4696                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName,                                    "Test importing again over previously imported semaphore.",                             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreImportReimport,                    config);
4697                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,               "Test importing semaphore multiple times.",                                                             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreMultipleImports,                   config);
4698                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,   "Test signaling, exporting, importing and waiting for the sempahore.",  checkEvent,             initProgramsToGetNativeFd,      testSemaphoreSignalExportImportWait,    config);
4699                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName,                               "Test signaling and importing the semaphore.",                                                  checkSupport,   initProgramsToGetNativeFd,      testSemaphoreSignalImport,                              config);
4700                 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName,                                "Test semaphores transference.",                                                                                checkEvent,             initProgramsToGetNativeFd,      testSemaphoreTransference,                              config);
4701
4702                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4703                 {
4704                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName,                     "Test import signaled semaphore fd.",                                                                           initProgramsToGetNativeFd,      testSemaphoreImportSyncFdSignaled,      config);
4705                 }
4706
4707
4708                 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4709                         || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4710                 {
4711                         // \note Not supported on WIN32 handles
4712                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,       "Test exporting semaphore multiple times.",             checkSupport,   initProgramsToGetNativeFd,      testSemaphoreMultipleExports,   config);
4713
4714                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName,                                         "Test calling dup() on exported semaphore.",    checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup,                             config);
4715                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName,                                        "Test calling dup2() on exported semaphore.",   checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup2,                    config);
4716                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName,                                        "Test calling dup3() on exported semaphore.",   checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdDup3,                    config);
4717                         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,            "Test sending semaphore fd over socket.",               checkSupport,   initProgramsToGetNativeFd,      testSemaphoreFdSendOverSocket,  config);
4718                 }
4719
4720                 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4721                 {
4722                         addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,                      "Test signaling and then waiting for the the sepmahore.",                               testSemaphoreSignalWaitImport,                  config);
4723                         addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,       "Test exporting, signaling, importing and waiting for the semaphore.",  testSemaphoreExportSignalImportWait,    config);
4724                         addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,       "Test exporting, importing, signaling and waiting for the semaphore.",  checkEvent,             testSemaphoreExportImportSignalWait,    config);
4725                 }
4726         }
4727
4728         return semaphoreGroup;
4729 }
4730
4731 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4732 {
4733         de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4734
4735         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4736         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4737         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4738         semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4739
4740         return semaphoreGroup;
4741 }
4742
4743 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4744 {
4745         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4746
4747         for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4748         {
4749                 const bool                                              dedicated               (dedicatedNdx == 1);
4750                 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup  (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4751
4752                 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4753                 {
4754                         const bool                                              hostVisible                     (hostVisibleNdx == 1);
4755                         de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup        (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4756                         const MemoryTestConfig                  memoryConfig            (externalType, hostVisible, dedicated);
4757
4758                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4759                                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4760                         {
4761                                 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .",         testMemoryWin32Create,  memoryConfig);
4762                         }
4763
4764                         addFunctionCase(hostVisibleGroup.get(), "import_twice",                         "Test importing memory object twice.",                  testMemoryImportTwice,          memoryConfig);
4765                         addFunctionCase(hostVisibleGroup.get(), "import_multiple_times",        "Test importing memory object multiple times.", testMemoryMultipleImports,      memoryConfig);
4766
4767                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4768                                 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4769                         {
4770                                 addFunctionCase(hostVisibleGroup.get(), "dup",                                          "Test calling dup() on exported memory.",       testMemoryFdDup,                        memoryConfig);
4771                                 addFunctionCase(hostVisibleGroup.get(), "dup2",                                         "Test calling dup2() on exported memory.",      testMemoryFdDup2,                       memoryConfig);
4772                                 addFunctionCase(hostVisibleGroup.get(), "dup3",                                         "Test calling dup3() on exported memory.",      testMemoryFdDup3,                       memoryConfig);
4773                                 addFunctionCase(hostVisibleGroup.get(), "send_over_socket",                     "Test sending memory fd over socket.",          testMemoryFdSendOverSocket,     memoryConfig);
4774                                 // \note Not supported on WIN32 handles
4775                                 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times",        "Test exporting memory multiple times.",        testMemoryMultipleExports,      memoryConfig);
4776                         }
4777
4778                         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4779                         {
4780                                 addFunctionCase(hostVisibleGroup.get(), "fd_properties",                        "Test obtaining the FD memory properties",      testMemoryFdProperties,         memoryConfig);
4781                         }
4782
4783                         dedicatedGroup->addChild(hostVisibleGroup.release());
4784                 }
4785
4786                 {
4787                         de::MovePtr<tcu::TestCaseGroup> bufferGroup             (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4788                         const BufferTestConfig                  bufferConfig    (externalType, dedicated);
4789
4790                         addFunctionCase(bufferGroup.get(), "info",                                              "External buffer memory info query.",                                           testBufferQueries,                              externalType);
4791                         addFunctionCase(bufferGroup.get(), "bind_export_import_bind",   "Test binding, exporting, importing and binding buffer.",       testBufferBindExportImportBind, bufferConfig);
4792                         addFunctionCase(bufferGroup.get(), "export_bind_import_bind",   "Test exporting, binding, importing and binding buffer.",       testBufferExportBindImportBind, bufferConfig);
4793                         addFunctionCase(bufferGroup.get(), "export_import_bind_bind",   "Test exporting, importing and binding buffer.",                        testBufferExportImportBindBind, bufferConfig);
4794
4795                         dedicatedGroup->addChild(bufferGroup.release());
4796                 }
4797
4798                 {
4799                         de::MovePtr<tcu::TestCaseGroup> imageGroup      (new tcu::TestCaseGroup(testCtx, "image", ""));
4800                         const ImageTestConfig                   imageConfig     (externalType, dedicated);
4801
4802                         addFunctionCase(imageGroup.get(), "info",                                               "External image memory info query.",                                            testImageQueries,                               externalType);
4803                         addFunctionCase(imageGroup.get(), "bind_export_import_bind",    "Test binding, exporting, importing and binding image.",        testImageBindExportImportBind,  imageConfig);
4804                         addFunctionCase(imageGroup.get(), "export_bind_import_bind",    "Test exporting, binding, importing and binding image.",        testImageExportBindImportBind,  imageConfig);
4805                         addFunctionCase(imageGroup.get(), "export_import_bind_bind",    "Test exporting, importing and binding image.",                         testImageExportImportBindBind,  imageConfig);
4806
4807                         dedicatedGroup->addChild(imageGroup.release());
4808                 }
4809
4810                 group->addChild(dedicatedGroup.release());
4811         }
4812
4813         if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4814         {
4815                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4816
4817                 const vk::VkFormat      ahbFormats[]    =
4818                 {
4819                         vk::VK_FORMAT_R8G8B8_UNORM,
4820                         vk::VK_FORMAT_R8G8B8A8_UNORM,
4821                         vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4822                         vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4823                         vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4824                         vk::VK_FORMAT_D16_UNORM,
4825                         vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4826                         vk::VK_FORMAT_D24_UNORM_S8_UINT,
4827                         vk::VK_FORMAT_D32_SFLOAT,
4828                         vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4829                         vk::VK_FORMAT_S8_UINT,
4830                 };
4831                 const size_t            numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4832
4833                 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4834                 {
4835                         const vk::VkFormat      format                  = ahbFormats[ahbFormatNdx];
4836                         const std::string       testCaseName    = getFormatCaseName(format);
4837
4838                         addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4839                 }
4840
4841                 group->addChild(formatGroup.release());
4842         }
4843
4844         return group;
4845 }
4846
4847 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4848 {
4849         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4850
4851         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4852         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4853         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4854         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4855         group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4856
4857         return group;
4858 }
4859
4860 } // anonymous
4861
4862 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4863 {
4864         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4865
4866         group->addChild(createSemaphoreTests(testCtx).release());
4867         group->addChild(createMemoryTests(testCtx).release());
4868         group->addChild(createFenceTests(testCtx).release());
4869
4870         return group.release();
4871 }
4872
4873 } // api
4874 } // vkt