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