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