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