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