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