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