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