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