• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, nullptr, buffer};
96     vk::VkMemoryDedicatedRequirements dedicatedRequirements = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
97                                                                nullptr, 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                                                                 nullptr, image};
111     vk::VkMemoryDedicatedRequirements dedicatedRequirements  = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
112                                                                 nullptr, 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=nullptr)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 = nullptr)
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, nullptr, 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                                                      nullptr,
343 
344                                                      (uint32_t)deviceExtensions.size(),
345                                                      deviceExtensions.empty() ? nullptr : &deviceExtensions[0],
346                                                      nullptr};
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, nullptr, externalType};
385     vk::VkExternalSemaphoreProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, nullptr, 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                                                         nullptr, externalType};
402     vk::VkExternalFenceProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, nullptr, 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                                                          nullptr,
419 
420                                                          createFlag, usageFlag, externalType};
421     vk::VkExternalBufferProperties properties         = {vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
422                                                          nullptr,
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, nullptr, 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, nullptr, {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                                      nullptr,
481 
482                                      0u,
483                                      nullptr,
484                                      nullptr,
485 
486                                      0u,
487                                      nullptr,
488 
489                                      1u,
490                                      &semaphore};
491 
492     VK_CHECK(vkd.queueSubmit(queue, 1, &submit, VK_NULL_HANDLE));
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_NULL_HANDLE));
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         nullptr,
682 
683         1u,
684         &semaphore,
685         &stage,
686 
687         0u,
688         nullptr,
689 
690         0u,
691         nullptr,
692     };
693 
694     VK_CHECK(vkd.queueSubmit(queue, 1, &submit, VK_NULL_HANDLE));
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                                      nullptr,
701 
702                                      0u,
703                                      nullptr,
704                                      nullptr,
705 
706                                      0u,
707                                      nullptr,
708 
709                                      0u,
710                                      nullptr};
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, nullptr, 0u};
727 
728     const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, nullptr));
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                                      nullptr,
777 
778                                      0u,
779                                      nullptr,
780                                      nullptr,
781 
782                                      1u,
783                                      &cmdBuffer.get(),
784 
785                                      0u,
786                                      nullptr};
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::__anon918cd0dc0111::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         nullptr,
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, nullptr, 0u,
829                                                     0u, 0u};
830 
831     vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
832     log << TestLog::Message << properties << TestLog::EndMessage;
833 
834     TCU_CHECK(properties.pNext == nullptr);
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::__anon918cd0dc0111::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, nullptr,
907 
908             (vk::pt::Win32SecurityAttributesPtr) nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
909             (vk::pt::Win32LPCWSTR) nullptr};
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                                                         nullptr, externalType};
1946     vk::VkExternalFenceProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, nullptr, 0u, 0u, 0u};
1947 
1948     vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1949     log << TestLog::Message << properties << TestLog::EndMessage;
1950 
1951     TCU_CHECK(properties.pNext == nullptr);
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::__anon918cd0dc0111::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, nullptr,
1990 
1991             (vk::pt::Win32SecurityAttributesPtr) nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1992             (vk::pt::Win32LPCWSTR) nullptr};
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, nullptr, createFlag, usageFlag,
3129                 externalType};
3130             vk::VkExternalBufferProperties properties = {
3131                 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, nullptr, {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 == nullptr);
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, nullptr,
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::__anon918cd0dc0111::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, nullptr,
3308 
3309         (vk::pt::Win32SecurityAttributesPtr) nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3310         (vk::pt::Win32LPCWSTR) nullptr};
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_NULL_HANDLE));
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             nullptr,                                                          // 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_NULL_HANDLE));
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             nullptr,                                                          // 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_NULL_HANDLE));
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_NULL_HANDLE));
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_NULL_HANDLE));
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_NULL_HANDLE));
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_NULL_HANDLE));
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_NULL_HANDLE));
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::__anon918cd0dc0111::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_NULL_HANDLE));
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             nullptr,                                                          // 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_NULL_HANDLE));
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             nullptr,                                                          // 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_NULL_HANDLE));
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             nullptr,                                                          // 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, nullptr, 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, nullptr, {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 == nullptr);
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::__anon918cd0dc0111::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_NULL_HANDLE));
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_NULL_HANDLE));
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_NULL_HANDLE));
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 ahbFormatProperties2,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 ahbFormatProperties2,
4662                              bool &enableMaxLayerTest)
4663 {
4664     DE_UNREF(createFlag);
4665 
4666     AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4667 
4668     if (!ahbApi)
4669     {
4670         TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4671     }
4672 
4673 #if (DE_OS == DE_OS_ANDROID)
4674     // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4675     if (!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4676         return false;
4677 #endif
4678 
4679     vk::pt::AndroidHardwareBufferPtr ahb =
4680         ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4681     if (ahb.internal == nullptr)
4682     {
4683         enableMaxLayerTest = false;
4684         // try again with layerCount '1'
4685         ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4686         if (ahb.internal == nullptr)
4687         {
4688             return false;
4689         }
4690     }
4691     NativeHandle nativeHandle(ahb);
4692 
4693     const vk::VkComponentMapping mappingA = {vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY,
4694                                              vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY};
4695     const vk::VkComponentMapping mappingB = {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G,
4696                                              vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A};
4697 
4698     for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4699     {
4700         // Both mappings should be equivalent and work.
4701         const vk::VkComponentMapping &mapping = ((variantIdx == 0) ? mappingA : mappingB);
4702 
4703         vk::VkAndroidHardwareBufferFormatProperties2ANDROID formatProperties2 = {
4704             vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID,
4705             nullptr,
4706             vk::VK_FORMAT_UNDEFINED,
4707             0u,
4708             0u,
4709             mapping,
4710             vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4711             vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4712             vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4713             vk::VK_CHROMA_LOCATION_COSITED_EVEN};
4714 
4715         vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties = {
4716             vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4717             nullptr,
4718             vk::VK_FORMAT_UNDEFINED,
4719             0u,
4720             0u,
4721             mapping,
4722             vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4723             vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4724             vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4725             vk::VK_CHROMA_LOCATION_COSITED_EVEN};
4726 
4727         void *pNext = ahbFormatProperties2 ? (void *)&formatProperties2 : (void *)&formatProperties;
4728 
4729         vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
4730             vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, pNext, 0u, 0u};
4731 
4732         try
4733         {
4734             VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4735             if (ahbFormatProperties2)
4736             {
4737                 TCU_CHECK(formatProperties2.format != vk::VK_FORMAT_UNDEFINED);
4738                 TCU_CHECK(formatProperties2.format == format);
4739                 TCU_CHECK(formatProperties2.externalFormat != 0u);
4740                 TCU_CHECK((formatProperties2.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4741                 TCU_CHECK((formatProperties2.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
4742                                                                vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) !=
4743                           0u);
4744 
4745                 bufferProperties.pNext = &formatProperties;
4746                 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4747                 TCU_CHECK((formatProperties2.formatFeatures & formatProperties.formatFeatures) ==
4748                           formatProperties.formatFeatures);
4749             }
4750             else
4751             {
4752                 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4753                 TCU_CHECK(formatProperties.format == format);
4754                 TCU_CHECK(formatProperties.externalFormat != 0u);
4755                 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4756                 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
4757                                                               vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4758             }
4759         }
4760         catch (const tcu::Exception &exception)
4761         {
4762             log << TestLog::Message << "Failure validating Android Hardware Buffer. See error message and combination: "
4763                 << TestLog::EndMessage;
4764             generateFailureText(log, format, usageFlag, createFlag, static_cast<vk::VkImageTiling>(0), 0, 0,
4765                                 exception.getMessage());
4766             return false;
4767         }
4768     }
4769 
4770     return true;
4771 }
4772 
4773 struct AndroidHardwareBufferImageFormatConfig
4774 {
AndroidHardwareBufferImageFormatConfigvkt::api::__anon918cd0dc0111::AndroidHardwareBufferImageFormatConfig4775     AndroidHardwareBufferImageFormatConfig(vk::VkFormat format_, bool ahb_format_properties2_)
4776         : format(format_)
4777         , ahb_format_properties2(ahb_format_properties2_)
4778     {
4779     }
4780 
4781     vk::VkFormat format;
4782     bool ahb_format_properties2;
4783 };
4784 
testAndroidHardwareBufferImageFormat(Context & context,AndroidHardwareBufferImageFormatConfig config)4785 tcu::TestStatus testAndroidHardwareBufferImageFormat(Context &context, AndroidHardwareBufferImageFormatConfig config)
4786 {
4787     AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4788     if (!ahbApi)
4789     {
4790         TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4791     }
4792     if (config.ahb_format_properties2)
4793     {
4794         context.requireDeviceFunctionality("VK_KHR_format_feature_flags2");
4795     }
4796 
4797     const vk::VkFormat format = config.format;
4798 
4799     bool testsFailed = false;
4800 
4801     const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType =
4802         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4803     const vk::PlatformInterface &vkp(context.getPlatformInterface());
4804     const CustomInstance instance(createTestInstance(context, 0u, externalMemoryType, 0u));
4805     const vk::InstanceDriver &vki(instance.getDriver());
4806     const vk::VkPhysicalDevice physicalDevice(
4807         vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4808 
4809     vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4810     protectedFeatures.sType           = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4811     protectedFeatures.pNext           = nullptr;
4812     protectedFeatures.protectedMemory = VK_FALSE;
4813 
4814     vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4815     deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4816     deviceFeatures.pNext = &protectedFeatures;
4817 
4818     vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4819 
4820     const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4821     const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
4822                                                            externalMemoryType, 0u, queueFamilyIndex, false,
4823                                                            &protectedFeatures));
4824     const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4825                                context.getTestContext().getCommandLine());
4826     TestLog &log                            = context.getTestContext().getLog();
4827     const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4828 
4829     const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ?
4830                                                               vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
4831                                                               vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4832 
4833     const vk::VkImageUsageFlagBits usageFlags[] = {
4834         vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4835         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4836         vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4837         vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4838         framebufferUsageFlag,
4839     };
4840     const vk::VkImageCreateFlagBits createFlags[] = {
4841         vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4842         vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4843         vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4844         vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4845     };
4846     const vk::VkImageTiling tilings[] = {
4847         vk::VK_IMAGE_TILING_OPTIMAL,
4848         vk::VK_IMAGE_TILING_LINEAR,
4849     };
4850     uint64_t mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4851     const size_t one                  = 1u;
4852     const size_t numOfUsageFlags      = DE_LENGTH_OF_ARRAY(usageFlags);
4853     const size_t numOfCreateFlags     = DE_LENGTH_OF_ARRAY(createFlags);
4854     const size_t numOfFlagCombos      = one << (numOfUsageFlags + numOfCreateFlags);
4855     const size_t numOfTilings         = DE_LENGTH_OF_ARRAY(tilings);
4856 
4857     for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4858     {
4859         vk::VkImageUsageFlags usage       = 0;
4860         vk::VkImageCreateFlags createFlag = 0;
4861         uint64_t requiredAhbUsage         = 0;
4862         bool enableMaxLayerTest           = true;
4863         for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4864         {
4865             if ((combo & (one << usageNdx)) == 0)
4866                 continue;
4867             usage |= usageFlags[usageNdx];
4868             requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4869         }
4870         for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4871         {
4872             const size_t bit = numOfUsageFlags + createFlagNdx;
4873             if ((combo & (one << bit)) == 0)
4874                 continue;
4875             if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) ==
4876                  vk::VK_IMAGE_CREATE_PROTECTED_BIT) &&
4877                 (protectedFeatures.protectedMemory == VK_FALSE))
4878                 continue;
4879 
4880             createFlag |= createFlags[createFlagNdx];
4881             requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4882         }
4883 
4884         // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4885         if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4886             continue;
4887 
4888         // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4889         if (!ValidateAHardwareBuffer(log, format, requiredAhbUsage, vkd, *device, usage, createFlag,
4890                                      limits.maxImageArrayLayers, config.ahb_format_properties2, enableMaxLayerTest))
4891             continue;
4892 
4893         bool foundAnyUsableTiling = false;
4894         for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4895         {
4896             const vk::VkImageTiling tiling = tilings[tilingIndex];
4897 
4898             const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo = {
4899                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, nullptr,
4900                 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID};
4901             const vk::VkPhysicalDeviceImageFormatInfo2 info = {
4902                 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4903                 &externalInfo,
4904                 format,
4905                 vk::VK_IMAGE_TYPE_2D,
4906                 tiling,
4907                 usage,
4908                 createFlag,
4909             };
4910 
4911             vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties = {
4912                 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID, nullptr, 0u};
4913             vk::VkExternalImageFormatProperties externalProperties = {
4914                 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, &ahbUsageProperties, {0u, 0u, 0u}};
4915             vk::VkImageFormatProperties2 properties = {
4916                 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &externalProperties, {{0u, 0u, 0u}, 0u, 0u, 0u, 0u}};
4917 
4918             if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) ==
4919                 vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4920             {
4921                 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4922                 continue;
4923             }
4924 
4925             foundAnyUsableTiling = true;
4926 
4927             try
4928             {
4929                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4930                            vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4931                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4932                            vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4933                 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4934                            vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4935                 uint32_t maxWidth  = properties.imageFormatProperties.maxExtent.width;
4936                 uint32_t maxHeight = properties.imageFormatProperties.maxExtent.height;
4937                 TCU_CHECK(maxWidth >= 4096);
4938                 TCU_CHECK(maxHeight >= 4096);
4939                 // Even if not requested, at least one of GPU_* usage flags must be present.
4940                 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4941                 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4942                 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4943             }
4944             catch (const tcu::Exception &exception)
4945             {
4946                 generateFailureText(log, format, usage, createFlag, tiling, 0, 0, exception.getMessage());
4947                 testsFailed = true;
4948                 continue;
4949             }
4950 
4951             log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage
4952                 << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4953                 << TestLog::EndMessage;
4954 
4955             struct ImageSize
4956             {
4957                 uint32_t width;
4958                 uint32_t height;
4959             };
4960             ImageSize sizes[] = {
4961                 {64u, 64u},
4962                 {1024u, 2096u},
4963             };
4964 
4965             uint32_t exportedMemoryTypeIndex = 0;
4966 
4967             if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4968             {
4969                 const vk::VkPhysicalDeviceMemoryProperties memProperties(
4970                     vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4971 
4972                 for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4973                 {
4974                     if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4975                     {
4976                         exportedMemoryTypeIndex = memoryTypeIndex;
4977                         break;
4978                     }
4979                 }
4980             }
4981 
4982             for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4983             {
4984                 try
4985                 {
4986                     const vk::Unique<vk::VkImage> image(
4987                         createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width,
4988                                             sizes[i].height, tiling, createFlag, usage));
4989                     const vk::VkMemoryRequirements requirements(
4990                         getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4991                     const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
4992                         vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4993                     NativeHandle handle;
4994 
4995                     VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4996                     getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4997 
4998                     uint32_t ahbFormat = 0;
4999                     uint64_t anhUsage  = 0;
5000                     ahbApi->describe(handle.getAndroidHardwareBuffer(), nullptr, nullptr, nullptr, &ahbFormat,
5001                                      &anhUsage, nullptr);
5002                     TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
5003                     TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
5004 
5005                     // Let watchdog know we're alive
5006                     context.getTestContext().touchWatchdog();
5007                 }
5008                 catch (const tcu::Exception &exception)
5009                 {
5010                     generateFailureText(log, format, usage, createFlag, tiling, sizes[i].width, sizes[i].height,
5011                                         exception.getMessage());
5012                     testsFailed = true;
5013                     continue;
5014                 }
5015             }
5016 
5017             if (properties.imageFormatProperties.maxMipLevels >= 7u)
5018             {
5019                 try
5020                 {
5021                     const vk::Unique<vk::VkImage> image(createExternalImage(vkd, *device, queueFamilyIndex,
5022                                                                             externalMemoryType, format, 64u, 64u,
5023                                                                             tiling, createFlag, usage, 7u));
5024                     const vk::VkMemoryRequirements requirements(
5025                         getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
5026                     const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
5027                         vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
5028                     NativeHandle handle;
5029 
5030                     VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
5031                     getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
5032 
5033                     uint32_t ahbFormat = 0;
5034                     uint64_t anhUsage  = 0;
5035                     ahbApi->describe(handle.getAndroidHardwareBuffer(), nullptr, nullptr, nullptr, &ahbFormat,
5036                                      &anhUsage, nullptr);
5037                     TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
5038                     TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
5039                 }
5040                 catch (const tcu::Exception &exception)
5041                 {
5042                     generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
5043                     testsFailed = true;
5044                     continue;
5045                 }
5046             }
5047 
5048             if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
5049             {
5050                 try
5051                 {
5052                     const vk::Unique<vk::VkImage> image(createExternalImage(
5053                         vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage,
5054                         1u, properties.imageFormatProperties.maxArrayLayers));
5055                     const vk::VkMemoryRequirements requirements(
5056                         getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
5057                     const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
5058                         vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
5059                     NativeHandle handle;
5060 
5061                     VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
5062                     getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
5063 
5064                     uint32_t ahbFormat = 0;
5065                     uint64_t anhUsage  = 0;
5066                     ahbApi->describe(handle.getAndroidHardwareBuffer(), nullptr, nullptr, nullptr, &ahbFormat,
5067                                      &anhUsage, nullptr);
5068                     TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
5069                     TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
5070                 }
5071                 catch (const tcu::Exception &exception)
5072                 {
5073                     generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
5074                     testsFailed = true;
5075                     continue;
5076                 }
5077             }
5078         }
5079 
5080         if (!foundAnyUsableTiling)
5081         {
5082             generateFailureText(log, format, usage, createFlag, static_cast<vk::VkImageTiling>(0));
5083             testsFailed = true;
5084             continue;
5085         }
5086     }
5087 
5088     if (testsFailed)
5089         return tcu::TestStatus::fail("Failure in at least one subtest. Check log for failed tests.");
5090     else
5091         return tcu::TestStatus::pass("Pass");
5092 }
5093 
5094 class AhbExternalFormatResolveApiCase : public TestCase
5095 {
5096 public:
5097     AhbExternalFormatResolveApiCase(tcu::TestContext &context, const std::string &name,
5098                                     AndroidHardwareBufferInstance::Format format, bool ahbFormatProperties2);
5099 
5100     TestInstance *createInstance(Context &context) const override;
5101     void checkSupport(Context &context) const override;
5102 
5103 private:
5104     const AndroidHardwareBufferInstance::Format m_format;
5105     const bool m_ahbFormatProperties2;
5106 };
5107 
5108 class AhbExternalFormatResolveApiInstance : public TestInstance
5109 {
5110 public:
5111     AhbExternalFormatResolveApiInstance(Context &context, AndroidHardwareBufferInstance::Format format,
5112                                         bool ahbFormatProperties2);
5113 
5114     tcu::TestStatus iterate(void) override;
5115 
5116 private:
5117     const AndroidHardwareBufferInstance::Format m_format;
5118     const bool m_ahbFormatProperties2;
5119     const AndroidHardwareBufferInstance::Usage m_usage =
5120         static_cast<AndroidHardwareBufferInstance::Usage>(AndroidHardwareBufferInstance::Usage::GPU_FRAMEBUFFER);
5121     const uint32_t m_width  = 32u;
5122     const uint32_t m_height = 32u;
5123     const uint32_t m_layers = 1u;
5124 };
5125 
AhbExternalFormatResolveApiCase(tcu::TestContext & context,const std::string & name,AndroidHardwareBufferInstance::Format format,bool ahbFormatProperties2)5126 AhbExternalFormatResolveApiCase::AhbExternalFormatResolveApiCase(tcu::TestContext &context, const std::string &name,
5127                                                                  AndroidHardwareBufferInstance::Format format,
5128                                                                  bool ahbFormatProperties2)
5129     : TestCase(context, name)
5130     , m_format(format)
5131     , m_ahbFormatProperties2(ahbFormatProperties2)
5132 {
5133 }
5134 
createInstance(Context & context) const5135 TestInstance *AhbExternalFormatResolveApiCase::createInstance(Context &context) const
5136 {
5137     return new AhbExternalFormatResolveApiInstance(context, m_format, m_ahbFormatProperties2);
5138 }
5139 
checkSupport(Context & context) const5140 void AhbExternalFormatResolveApiCase::checkSupport(Context &context) const
5141 {
5142     context.requireDeviceFunctionality("VK_ANDROID_external_format_resolve");
5143 
5144     if (!AndroidHardwareBufferExternalApi::getInstance())
5145         TCU_THROW(NotSupportedError, "No AHB api peresent");
5146 
5147     if (m_ahbFormatProperties2)
5148         context.requireDeviceFunctionality("VK_KHR_format_feature_flags2");
5149 }
5150 
AhbExternalFormatResolveApiInstance(Context & context,AndroidHardwareBufferInstance::Format format,bool ahbFormatProperties2)5151 AhbExternalFormatResolveApiInstance::AhbExternalFormatResolveApiInstance(Context &context,
5152                                                                          AndroidHardwareBufferInstance::Format format,
5153                                                                          bool ahbFormatProperties2)
5154     : TestInstance(context)
5155     , m_format(format)
5156     , m_ahbFormatProperties2(ahbFormatProperties2)
5157 {
5158 }
5159 
iterate(void)5160 tcu::TestStatus AhbExternalFormatResolveApiInstance::iterate(void)
5161 {
5162     const vk::DeviceInterface &vk            = m_context.getDeviceInterface();
5163     const vk::VkDevice device                = m_context.getDevice();
5164     tcu::TestLog &log                        = m_context.getTestContext().getLog();
5165     AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
5166 
5167     if (!ahbApi)
5168         TCU_THROW(NotSupportedError, "Android Hardware Buffer not present");
5169 
5170     AndroidHardwareBufferInstance androidBuffer;
5171 
5172     // If the allocation failed it means AHB format is not supported, test next
5173     if (!androidBuffer.allocate(m_format, m_width, m_height, m_layers, m_usage))
5174     {
5175         std::string skipReason = "Unable to allocate renderable AHB with parameters: width(" + std::to_string(m_width) +
5176                                  "), height(" + std::to_string(m_height) + "), layers(" + std::to_string(m_layers) +
5177                                  "), usage(" + std::to_string(m_usage) + ")";
5178 
5179         log << tcu::TestLog::Message << skipReason << tcu::TestLog::EndMessage;
5180         TCU_THROW(NotSupportedError, "Failed to allocate buffer");
5181     }
5182 
5183     vk::VkAndroidHardwareBufferFormatResolvePropertiesANDROID formatResolveProperties = {
5184         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID, // VkStructureType    sType
5185         nullptr,                                                                         // void*            pNext
5186         vk::VK_FORMAT_UNDEFINED // VkFormat            colorAttachmentFormat
5187     };
5188 
5189     vk::VkAndroidHardwareBufferFormatProperties2ANDROID formatProperties2 = {
5190         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID, // VkStructureType sType;
5191         &formatResolveProperties,                                                  // void* pNext;
5192         vk::VK_FORMAT_UNDEFINED,                                                   // VkFormat format;
5193         0u,                                                                        // uint64_t externalFormat;
5194         0u,                                                 // VkFormatFeatureFlags2 formatFeatures;
5195         vk::VkComponentMapping(),                           // VkComponentMapping samplerYcbcrConversionComponents;
5196         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, // VkSamplerYcbcrModelConversion suggestedYcbcrModel;
5197         vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,                // VkSamplerYcbcrRange suggestedYcbcrRange;
5198         vk::VK_CHROMA_LOCATION_COSITED_EVEN,                // VkChromaLocation suggestedXChromaOffset;
5199         vk::VK_CHROMA_LOCATION_COSITED_EVEN,                // VkChromaLocation suggestedYChromaOffset;
5200     };
5201 
5202     vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties = {
5203         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, // VkStructureType                    sType
5204         &formatResolveProperties, // void*                            pNext
5205         vk::VK_FORMAT_UNDEFINED,  // VkFormat                            format
5206         0u,                       // uint64_t                            externalFormat
5207         0u,                       // VkFormatFeatureFlags                formatFeatures
5208         vk::VkComponentMapping(), // VkComponentMapping                samplerYcbcrConversionComponents
5209         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, // VkSamplerYcbcrModelConversion    suggestedYcbcrModel
5210         vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,                // VkSamplerYcbcrRange                suggestedYcbcrRange
5211         vk::VK_CHROMA_LOCATION_COSITED_EVEN, // VkChromaLocation                    suggestedXChromaOffset
5212         vk::VK_CHROMA_LOCATION_COSITED_EVEN  // VkChromaLocation                    suggestedYChromaOffset
5213     };
5214 
5215     void *pNext = m_ahbFormatProperties2 ? (void *)&formatProperties2 : (void *)&formatProperties;
5216 
5217     vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
5218         vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType    sType
5219         pNext,                                                            // void*            pNext
5220         0u,                                                               // VkDeviceSize        allocationSize
5221         0u                                                                // uint32_t            memoryTypeBits
5222     };
5223 
5224     VK_CHECK(vk.getAndroidHardwareBufferPropertiesANDROID(device, androidBuffer.getHandle(), &bufferProperties));
5225 
5226     vk::VkFormat format = m_ahbFormatProperties2 ? formatProperties2.format : formatProperties.format;
5227     if (format != vk::VK_FORMAT_UNDEFINED)
5228     {
5229         vk::VkFormatProperties3 colorAttachmentFormatProperties = m_context.getFormatProperties(format);
5230         vk::VkFormatFeatureFlags requiredFlags =
5231             vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
5232 
5233         if ((colorAttachmentFormatProperties.optimalTilingFeatures & requiredFlags) ||
5234             (colorAttachmentFormatProperties.linearTilingFeatures & requiredFlags))
5235             return tcu::TestStatus::pass("");
5236         // Depth and stencil format must be supported through this path. No external format resolve is allowed for depth/stencil formats
5237         else if (AndroidHardwareBufferInstance::isFormatDepth(m_format) ||
5238                  AndroidHardwareBufferInstance::isFormatStencil(m_format))
5239             return tcu::TestStatus::fail("Depth/stencil must be supported through Vulkan Format mapping");
5240     }
5241 
5242     if (formatResolveProperties.colorAttachmentFormat != vk::VK_FORMAT_UNDEFINED)
5243     {
5244         vk::VkFormatProperties3 colorAttachmentFormatProperties =
5245             m_context.getFormatProperties(formatResolveProperties.colorAttachmentFormat);
5246 
5247         // External formats require optimal tiling
5248         if (colorAttachmentFormatProperties.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
5249             return tcu::TestStatus::pass("");
5250     }
5251 
5252     return tcu::TestStatus::fail("No draw support");
5253 }
5254 
checkMaintenance5(Context & context,vk::VkExternalMemoryHandleTypeFlagBits)5255 void checkMaintenance5(Context &context, vk::VkExternalMemoryHandleTypeFlagBits)
5256 {
5257     context.requireDeviceFunctionality("VK_KHR_maintenance5");
5258 }
5259 
createFenceTests(tcu::TestContext & testCtx)5260 de::MovePtr<tcu::TestCaseGroup> createFenceTests(tcu::TestContext &testCtx)
5261 {
5262     de::MovePtr<tcu::TestCaseGroup> fenceGroup(new tcu::TestCaseGroup(testCtx, "fence"));
5263 
5264     fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
5265     fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5266     fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5267     fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5268 
5269     return fenceGroup;
5270 }
5271 
createSemaphoreTests(tcu::TestContext & testCtx,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)5272 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests(tcu::TestContext &testCtx,
5273                                                      vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
5274 {
5275     const struct
5276     {
5277         const char *const name;
5278         const Permanence permanence;
5279     } permanences[] = {{"temporary", PERMANENCE_TEMPORARY}, {"permanent", PERMANENCE_PERMANENT}};
5280     const struct
5281     {
5282         const char *const name;
5283         vk::VkSemaphoreType type;
5284     } semaphoreTypes[] = {
5285         {"binary", vk::VK_SEMAPHORE_TYPE_BINARY},
5286         {"timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE},
5287     };
5288 
5289     de::MovePtr<tcu::TestCaseGroup> semaphoreGroup(
5290         new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType)));
5291 
5292     for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
5293     {
5294         // Test external semaphore queries
5295         addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
5296                         testSemaphoreQueries,
5297                         TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
5298     }
5299 
5300     for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
5301     {
5302         const Permanence permanence(permanences[permanenceNdx].permanence);
5303         const char *const permanenceName(permanences[permanenceNdx].name);
5304         const SemaphoreTestConfig config(externalType, permanence);
5305 
5306         if (!isSupportedPermanence(externalType, permanence))
5307             continue;
5308 
5309         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
5310             externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
5311         {
5312             // Test creating semaphore with win32 properties.
5313             addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,
5314                             testSemaphoreWin32Create, config);
5315         }
5316 
5317         // Test importing semaphore twice.
5318         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, checkSupport,
5319                                     initProgramsToGetNativeFd, testSemaphoreImportTwice, config);
5320         // Test importing again over previously imported semaphore.
5321         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, checkSupport,
5322                                     initProgramsToGetNativeFd, testSemaphoreImportReimport, config);
5323         // Test importing semaphore multiple times.
5324         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,
5325                                     checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config);
5326         // Test signaling, exporting, importing and waiting for the sempahore.
5327         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,
5328                                     checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config);
5329         // Test signaling and importing the semaphore.
5330         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, checkSupport,
5331                                     initProgramsToGetNativeFd, testSemaphoreSignalImport, config);
5332         // Test semaphores transference.
5333         addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, checkEvent,
5334                                     initProgramsToGetNativeFd, testSemaphoreTransference, config);
5335 
5336         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
5337         {
5338             // Test import signaled semaphore fd.
5339             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName,
5340                                         initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config);
5341         }
5342 
5343         if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT ||
5344             externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
5345         {
5346             // \note Not supported on WIN32 handles
5347             // Test exporting semaphore multiple times.
5348             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,
5349                                         checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config);
5350 
5351             // Test calling dup() on exported semaphore.
5352             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, checkSupport,
5353                                         initProgramsToGetNativeFd, testSemaphoreFdDup, config);
5354             // Test calling dup2() on exported semaphore.
5355             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, checkSupport,
5356                                         initProgramsToGetNativeFd, testSemaphoreFdDup2, config);
5357             // Test calling dup3() on exported semaphore.
5358             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, checkSupport,
5359                                         initProgramsToGetNativeFd, testSemaphoreFdDup3, config);
5360             // Test sending semaphore fd over socket.
5361             addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,
5362                                         checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config);
5363         }
5364 
5365         if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
5366         {
5367             // Test signaling and then waiting for the the sepmahore.
5368             addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,
5369                             testSemaphoreSignalWaitImport, config);
5370             // Test exporting, signaling, importing and waiting for the semaphore.
5371             addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,
5372                             testSemaphoreExportSignalImportWait, config);
5373             // Test exporting, importing, signaling and waiting for the semaphore.
5374             addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,
5375                             checkEvent, testSemaphoreExportImportSignalWait, config);
5376         }
5377     }
5378 
5379     return semaphoreGroup;
5380 }
5381 
createSemaphoreTests(tcu::TestContext & testCtx)5382 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests(tcu::TestContext &testCtx)
5383 {
5384     // Tests for external semaphores.
5385     de::MovePtr<tcu::TestCaseGroup> semaphoreGroup(new tcu::TestCaseGroup(testCtx, "semaphore"));
5386 
5387     semaphoreGroup->addChild(
5388         createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
5389     semaphoreGroup->addChild(
5390         createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5391     semaphoreGroup->addChild(
5392         createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5393     semaphoreGroup->addChild(
5394         createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5395     semaphoreGroup->addChild(
5396         createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA).release());
5397 
5398     return semaphoreGroup;
5399 }
5400 
createMemoryTests(tcu::TestContext & testCtx,vk::VkExternalMemoryHandleTypeFlagBits externalType)5401 de::MovePtr<tcu::TestCaseGroup> createMemoryTests(tcu::TestContext &testCtx,
5402                                                   vk::VkExternalMemoryHandleTypeFlagBits externalType)
5403 {
5404     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType)));
5405 
5406     for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
5407     {
5408         const bool dedicated(dedicatedNdx == 1);
5409         de::MovePtr<tcu::TestCaseGroup> dedicatedGroup(
5410             new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated"));
5411 
5412         for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
5413         {
5414             const bool hostVisible(hostVisibleNdx == 1);
5415             de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup(
5416                 new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only"));
5417             const MemoryTestConfig memoryConfig(externalType, hostVisible, dedicated);
5418 
5419             if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
5420                 externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
5421             {
5422                 // Test creating memory with win32 properties .
5423                 addFunctionCase(hostVisibleGroup.get(), "create_win32", testMemoryWin32Create, memoryConfig);
5424             }
5425 
5426             // Test importing memory object twice.
5427             addFunctionCase(hostVisibleGroup.get(), "import_twice", testMemoryImportTwice, memoryConfig);
5428             // Test importing memory object multiple times.
5429             addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", testMemoryMultipleImports, memoryConfig);
5430 
5431             if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
5432                 externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
5433             {
5434                 // Test calling dup() on exported memory.
5435                 addFunctionCase(hostVisibleGroup.get(), "dup", testMemoryFdDup, memoryConfig);
5436                 // Test calling dup2() on exported memory.
5437                 addFunctionCase(hostVisibleGroup.get(), "dup2", testMemoryFdDup2, memoryConfig);
5438                 // Test calling dup3() on exported memory.
5439                 addFunctionCase(hostVisibleGroup.get(), "dup3", testMemoryFdDup3, memoryConfig);
5440                 // Test sending memory fd over socket.
5441                 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", testMemoryFdSendOverSocket, memoryConfig);
5442                 // \note Not supported on WIN32 handles
5443                 // Test exporting memory multiple times.
5444                 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", testMemoryMultipleExports,
5445                                 memoryConfig);
5446             }
5447 
5448             if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
5449             {
5450                 // Test obtaining the FD memory properties
5451                 addFunctionCase(hostVisibleGroup.get(), "fd_properties", testMemoryFdProperties, memoryConfig);
5452             }
5453 
5454             dedicatedGroup->addChild(hostVisibleGroup.release());
5455         }
5456 
5457         {
5458             de::MovePtr<tcu::TestCaseGroup> bufferGroup(new tcu::TestCaseGroup(testCtx, "buffer"));
5459             const BufferTestConfig bufferConfig(externalType, dedicated);
5460 
5461             // External buffer memory info query.
5462             addFunctionCase(bufferGroup.get(), "info", testBufferQueries, externalType);
5463             // External buffer memory info query using BufferUsageFlags2CreateInfoKHR.
5464             addFunctionCase(bufferGroup.get(), "maintenance5", checkMaintenance5, testBufferQueriesMaintenance5,
5465                             externalType);
5466             // Test binding, exporting, importing and binding buffer.
5467             addFunctionCase(bufferGroup.get(), "bind_export_import_bind", testBufferBindExportImportBind, bufferConfig);
5468             // Test exporting, binding, importing and binding buffer.
5469             addFunctionCase(bufferGroup.get(), "export_bind_import_bind", testBufferExportBindImportBind, bufferConfig);
5470             // Test exporting, importing and binding buffer.
5471             addFunctionCase(bufferGroup.get(), "export_import_bind_bind", testBufferExportImportBindBind, bufferConfig);
5472 
5473             dedicatedGroup->addChild(bufferGroup.release());
5474         }
5475 
5476         {
5477             de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, "image"));
5478             const ImageTestConfig imageConfig(externalType, dedicated);
5479 
5480             // External image memory info query.
5481             addFunctionCase(imageGroup.get(), "info", testImageQueries, externalType);
5482             // Test binding, exporting, importing and binding image.
5483             addFunctionCase(imageGroup.get(), "bind_export_import_bind", testImageBindExportImportBind, imageConfig);
5484             // Test exporting, binding, importing and binding image.
5485             addFunctionCase(imageGroup.get(), "export_bind_import_bind", testImageExportBindImportBind, imageConfig);
5486             // Test exporting, importing and binding image.
5487             addFunctionCase(imageGroup.get(), "export_import_bind_bind", testImageExportImportBindBind, imageConfig);
5488 
5489             dedicatedGroup->addChild(imageGroup.release());
5490         }
5491 
5492         group->addChild(dedicatedGroup.release());
5493     }
5494 
5495     if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
5496     {
5497         for (size_t formatPropertiesNdx = 0; formatPropertiesNdx < 2; formatPropertiesNdx++)
5498         {
5499             const bool ahb_format_properties2 = formatPropertiesNdx == 1;
5500 
5501             const std::string ahb_format_properties_name =
5502                 ahb_format_properties2 ? "ahb_format_properties_2" : "ahb_format_properties";
5503 
5504             de::MovePtr<tcu::TestCaseGroup> ahbFormatPropertiesGroup(
5505                 new tcu::TestCaseGroup(testCtx, ahb_format_properties_name.c_str()));
5506 
5507             {
5508                 // Test minimum image format support
5509                 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, "image_formats"));
5510 
5511                 const vk::VkFormat ahbFormats[] = {
5512                     vk::VK_FORMAT_R8G8B8_UNORM,
5513                     vk::VK_FORMAT_R8G8B8A8_UNORM,
5514                     vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
5515                     vk::VK_FORMAT_R16G16B16A16_SFLOAT,
5516                     vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
5517                     vk::VK_FORMAT_D16_UNORM,
5518                     vk::VK_FORMAT_X8_D24_UNORM_PACK32,
5519                     vk::VK_FORMAT_D24_UNORM_S8_UINT,
5520                     vk::VK_FORMAT_D32_SFLOAT,
5521                     vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
5522                     vk::VK_FORMAT_S8_UINT,
5523                     vk::VK_FORMAT_R8_UNORM,
5524                     vk::VK_FORMAT_R16_UINT,
5525                     vk::VK_FORMAT_R16G16_UINT,
5526                     vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
5527                 };
5528                 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
5529 
5530                 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
5531                 {
5532                     const vk::VkFormat format = ahbFormats[ahbFormatNdx];
5533 
5534                     const std::string testCaseName = getFormatCaseName(format);
5535 
5536                     const AndroidHardwareBufferImageFormatConfig ahbImageFormatConfig(format, ahb_format_properties2);
5537 
5538                     addFunctionCase(formatGroup.get(), testCaseName, testAndroidHardwareBufferImageFormat,
5539                                     ahbImageFormatConfig);
5540                 }
5541 
5542                 ahbFormatPropertiesGroup->addChild(formatGroup.release());
5543             }
5544 
5545             {
5546                 // Test minimum image format support
5547                 de::MovePtr<tcu::TestCaseGroup> externalFormatResolve(
5548                     new tcu::TestCaseGroup(testCtx, "external_format_resolve"));
5549                 for (uint32_t i = 0u; i < AndroidHardwareBufferInstance::Format::COUNT; ++i)
5550                 {
5551                     const AndroidHardwareBufferInstance::Format format =
5552                         static_cast<AndroidHardwareBufferInstance::Format>(i);
5553                     if (AndroidHardwareBufferInstance::Format::BLOB == format)
5554                         continue;
5555 
5556                     const std::string formatName = AndroidHardwareBufferInstance::getFormatName(format);
5557                     externalFormatResolve->addChild(new AhbExternalFormatResolveApiCase(
5558                         externalFormatResolve->getTestContext(), formatName, format, ahb_format_properties2));
5559                 }
5560 
5561                 ahbFormatPropertiesGroup->addChild(externalFormatResolve.release());
5562             }
5563             group->addChild(ahbFormatPropertiesGroup.release());
5564         }
5565     }
5566 
5567     return group;
5568 }
5569 
createMemoryTests(tcu::TestContext & testCtx)5570 de::MovePtr<tcu::TestCaseGroup> createMemoryTests(tcu::TestContext &testCtx)
5571 {
5572     // Tests for external memory
5573     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "memory"));
5574 
5575     group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5576     group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5577     group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5578     group->addChild(
5579         createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
5580     group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
5581     group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA).release());
5582 
5583     return group;
5584 }
5585 
5586 } // namespace
5587 
createExternalMemoryTests(tcu::TestContext & testCtx)5588 tcu::TestCaseGroup *createExternalMemoryTests(tcu::TestContext &testCtx)
5589 {
5590     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "external"));
5591 
5592     group->addChild(createSemaphoreTests(testCtx).release());
5593     group->addChild(createMemoryTests(testCtx).release());
5594     group->addChild(createFenceTests(testCtx).release());
5595 
5596     return group.release();
5597 }
5598 
5599 } // namespace api
5600 } // namespace vkt
5601