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