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