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