1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group 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 *//*! 20 * \file 21 * \brief Synchronization tests for resources shared between instances. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktSynchronizationCrossInstanceSharingTests.hpp" 25 26 #include "vkDeviceUtil.hpp" 27 #include "vkPlatform.hpp" 28 #include "vktTestCaseUtil.hpp" 29 30 #include "vktSynchronizationUtil.hpp" 31 #include "vktSynchronizationOperation.hpp" 32 #include "vktSynchronizationOperationTestData.hpp" 33 #include "vktSynchronizationOperationResources.hpp" 34 #include "vktExternalMemoryUtil.hpp" 35 36 #include "tcuResultCollector.hpp" 37 #include "tcuTestLog.hpp" 38 39 using tcu::TestLog; 40 using namespace vkt::ExternalMemoryUtil; 41 42 namespace vkt 43 { 44 namespace synchronization 45 { 46 namespace 47 { 48 49 struct TestConfig 50 { 51 TestConfig (const ResourceDescription& resource_, 52 OperationName writeOp_, 53 OperationName readOp_, 54 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType_, 55 vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreHandleType_, 56 bool dedicated_) 57 : resource (resource_) 58 , writeOp (writeOp_) 59 , readOp (readOp_) 60 , memoryHandleType (memoryHandleType_) 61 , semaphoreHandleType (semaphoreHandleType_) 62 , dedicated (dedicated_) 63 { 64 } 65 66 const ResourceDescription resource; 67 const OperationName writeOp; 68 const OperationName readOp; 69 const vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType; 70 const vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreHandleType; 71 const bool dedicated; 72 }; 73 74 // A helper class to test for extensions upfront and throw not supported to speed up test runtimes compared to failing only 75 // after creating unnecessary vkInstances. A common example of this is win32 platforms taking a long time to run _fd tests. 76 class NotSupportedChecker 77 { 78 public: 79 NotSupportedChecker (const Context& context, 80 TestConfig config, 81 const OperationSupport& writeOp, 82 const OperationSupport& readOp) 83 : m_context (context) 84 { 85 // Check instance support 86 requireInstanceExtension("VK_KHR_get_physical_device_properties2"); 87 88 requireInstanceExtension("VK_KHR_external_semaphore_capabilities"); 89 requireInstanceExtension("VK_KHR_external_memory_capabilities"); 90 91 // Check device support 92 if (config.dedicated) 93 requireDeviceExtension("VK_KHR_dedicated_allocation"); 94 95 requireDeviceExtension("VK_KHR_external_semaphore"); 96 requireDeviceExtension("VK_KHR_external_memory"); 97 98 if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR 99 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR 100 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) 101 { 102 requireDeviceExtension("VK_KHR_external_semaphore_fd"); 103 requireDeviceExtension("VK_KHR_external_memory_fd"); 104 } 105 106 if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 107 || config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR 108 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 109 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR) 110 { 111 requireDeviceExtension("VK_KHR_external_semaphore_win32"); 112 requireDeviceExtension("VK_KHR_external_memory_win32"); 113 } 114 115 TestLog& log = context.getTestContext().getLog(); 116 const vk::InstanceInterface& vki = context.getInstanceInterface(); 117 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 118 119 // Check resource support 120 if (config.resource.type == RESOURCE_TYPE_IMAGE) 121 { 122 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo = 123 { 124 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, 125 DE_NULL, 126 config.memoryHandleType 127 }; 128 const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = 129 { 130 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, 131 &externalInfo, 132 config.resource.imageFormat, 133 config.resource.imageType, 134 vk::VK_IMAGE_TILING_OPTIMAL, 135 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(), 136 0u 137 }; 138 vk::VkExternalImageFormatProperties externalProperties = 139 { 140 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, 141 DE_NULL, 142 { 0u, 0u, 0u } 143 }; 144 vk::VkImageFormatProperties2 formatProperties = 145 { 146 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, 147 &externalProperties, 148 { 149 { 0u, 0u, 0u }, 150 0u, 151 0u, 152 0u, 153 0u, 154 } 155 }; 156 157 { 158 const vk::VkResult res = vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &formatProperties); 159 160 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) 161 TCU_THROW(NotSupportedError, "Image format not supported"); 162 163 VK_CHECK(res); // Check other errors 164 } 165 166 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage; 167 168 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0) 169 TCU_THROW(NotSupportedError, "Exporting image resource not supported"); 170 171 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0) 172 TCU_THROW(NotSupportedError, "Importing image resource not supported"); 173 174 if (!config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0) 175 { 176 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory"); 177 } 178 } 179 else 180 { 181 const vk::VkPhysicalDeviceExternalBufferInfo info = 182 { 183 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, 184 DE_NULL, 185 186 0u, 187 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(), 188 config.memoryHandleType 189 }; 190 vk::VkExternalBufferProperties properties = 191 { 192 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, 193 DE_NULL, 194 { 0u, 0u, 0u} 195 }; 196 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties); 197 198 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage; 199 200 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0 201 || (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0) 202 TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported"); 203 204 if (!config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0) 205 { 206 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory"); 207 } 208 } 209 210 // Check semaphore support 211 { 212 const vk::VkPhysicalDeviceExternalSemaphoreInfo info = 213 { 214 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, 215 DE_NULL, 216 config.semaphoreHandleType 217 }; 218 vk::VkExternalSemaphoreProperties properties; 219 220 vki.getPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &info, &properties); 221 222 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage; 223 224 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0 225 || (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0) 226 TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported"); 227 } 228 } 229 230 private: 231 void requireDeviceExtension(const char* name) const 232 { 233 if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), name)) 234 TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str()); 235 } 236 237 void requireInstanceExtension(const char* name) const 238 { 239 if (!de::contains(m_context.getInstanceExtensions().begin(), m_context.getInstanceExtensions().end(), name)) 240 TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str()); 241 } 242 243 const Context& m_context; 244 }; 245 246 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags) 247 { 248 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0) 249 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT; 250 251 return (availableFlags & neededFlags) != 0; 252 } 253 254 class SimpleAllocation : public vk::Allocation 255 { 256 public: 257 SimpleAllocation (const vk::DeviceInterface& vkd, 258 vk::VkDevice device, 259 const vk::VkDeviceMemory memory); 260 ~SimpleAllocation (void); 261 262 private: 263 const vk::DeviceInterface& m_vkd; 264 const vk::VkDevice m_device; 265 }; 266 267 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd, 268 vk::VkDevice device, 269 const vk::VkDeviceMemory memory) 270 : Allocation (memory, 0, DE_NULL) 271 , m_vkd (vkd) 272 , m_device (device) 273 { 274 } 275 276 SimpleAllocation::~SimpleAllocation (void) 277 { 278 m_vkd.freeMemory(m_device, getMemory(), DE_NULL); 279 } 280 281 class DeviceId 282 { 283 public: 284 DeviceId (deUint32 vendorId, 285 deUint32 driverVersion, 286 const deUint8 driverUUID[VK_UUID_SIZE], 287 const deUint8 deviceUUID[VK_UUID_SIZE]); 288 289 bool operator== (const DeviceId& other) const; 290 bool operator|= (const DeviceId& other) const; 291 292 private: 293 const deUint32 m_vendorId; 294 const deUint32 m_driverVersion; 295 deUint8 m_driverUUID[VK_UUID_SIZE]; 296 deUint8 m_deviceUUID[VK_UUID_SIZE]; 297 }; 298 299 DeviceId::DeviceId (deUint32 vendorId, 300 deUint32 driverVersion, 301 const deUint8 driverUUID[VK_UUID_SIZE], 302 const deUint8 deviceUUID[VK_UUID_SIZE]) 303 : m_vendorId (vendorId) 304 , m_driverVersion (driverVersion) 305 { 306 deMemcpy(m_driverUUID, driverUUID, sizeof(m_driverUUID)); 307 deMemcpy(m_deviceUUID, deviceUUID, sizeof(m_deviceUUID)); 308 } 309 310 bool DeviceId::operator== (const DeviceId& other) const 311 { 312 if (this == &other) 313 return true; 314 315 if (m_vendorId != other.m_vendorId) 316 return false; 317 318 if (m_driverVersion != other.m_driverVersion) 319 return false; 320 321 if (deMemCmp(m_driverUUID, other.m_driverUUID, sizeof(m_driverUUID)) != 0) 322 return false; 323 324 return deMemCmp(m_deviceUUID, other.m_deviceUUID, sizeof(m_deviceUUID)) == 0; 325 } 326 327 DeviceId getDeviceId (const vk::InstanceInterface& vki, 328 vk::VkPhysicalDevice physicalDevice) 329 { 330 vk::VkPhysicalDeviceIDProperties propertiesId; 331 vk::VkPhysicalDeviceProperties2 properties; 332 333 deMemset(&properties, 0, sizeof(properties)); 334 deMemset(&propertiesId, 0, sizeof(propertiesId)); 335 336 propertiesId.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; 337 338 properties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; 339 properties.pNext = &propertiesId; 340 341 vki.getPhysicalDeviceProperties2(physicalDevice, &properties); 342 343 return DeviceId(properties.properties.vendorID, properties.properties.driverVersion, propertiesId.driverUUID, propertiesId.deviceUUID); 344 } 345 346 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp, deUint32 version) 347 { 348 try 349 { 350 std::vector<std::string> extensions; 351 if (!vk::isCoreInstanceExtension(version, "VK_KHR_get_physical_device_properties2")) 352 extensions.push_back("VK_KHR_get_physical_device_properties2"); 353 if (!vk::isCoreInstanceExtension(version, "VK_KHR_external_semaphore_capabilities")) 354 extensions.push_back("VK_KHR_external_semaphore_capabilities"); 355 if (!vk::isCoreInstanceExtension(version, "VK_KHR_external_memory_capabilities")) 356 extensions.push_back("VK_KHR_external_memory_capabilities"); 357 358 return vk::createDefaultInstance(vkp, version, std::vector<std::string>(), extensions); 359 } 360 catch (const vk::Error& error) 361 { 362 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT) 363 TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance"); 364 else 365 throw; 366 } 367 } 368 369 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, 370 vk::VkInstance instance, 371 const tcu::CommandLine& cmdLine) 372 { 373 return vk::chooseDevice(vki, instance, cmdLine); 374 } 375 376 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, vk::VkInstance instance, const DeviceId& deviceId) 377 { 378 const std::vector<vk::VkPhysicalDevice> devices (vk::enumeratePhysicalDevices(vki, instance)); 379 380 for (size_t deviceNdx = 0; deviceNdx < devices.size(); deviceNdx++) 381 { 382 if (deviceId == getDeviceId(vki, devices[deviceNdx])) 383 return devices[deviceNdx]; 384 } 385 386 TCU_FAIL("No matching device found"); 387 388 return (vk::VkPhysicalDevice)0; 389 } 390 391 vk::Move<vk::VkDevice> createDevice (const deUint32 apiVersion, 392 const vk::InstanceInterface& vki, 393 vk::VkPhysicalDevice physicalDevice, 394 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType, 395 vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreHandleType, 396 bool dedicated, 397 bool khrMemReqSupported) 398 { 399 const float priority = 0.0f; 400 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice); 401 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu); 402 std::vector<const char*> extensions; 403 404 if (dedicated) 405 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation")) 406 extensions.push_back("VK_KHR_dedicated_allocation"); 407 408 if (khrMemReqSupported) 409 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2")) 410 extensions.push_back("VK_KHR_get_memory_requirements2"); 411 412 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore")) 413 extensions.push_back("VK_KHR_external_semaphore"); 414 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory")) 415 extensions.push_back("VK_KHR_external_memory"); 416 417 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT 418 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT 419 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) 420 { 421 extensions.push_back("VK_KHR_external_semaphore_fd"); 422 extensions.push_back("VK_KHR_external_memory_fd"); 423 } 424 425 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT 426 || memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT 427 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT 428 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT) 429 { 430 extensions.push_back("VK_KHR_external_semaphore_win32"); 431 extensions.push_back("VK_KHR_external_memory_win32"); 432 } 433 434 try 435 { 436 std::vector<vk::VkDeviceQueueCreateInfo> queues; 437 438 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++) 439 { 440 const vk::VkDeviceQueueCreateInfo createInfo = 441 { 442 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 443 DE_NULL, 444 0u, 445 446 (deUint32)ndx, 447 1u, 448 &priority 449 }; 450 451 queues.push_back(createInfo); 452 } 453 454 const vk::VkDeviceCreateInfo createInfo = 455 { 456 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 457 DE_NULL, 458 0u, 459 460 (deUint32)queues.size(), 461 &queues[0], 462 463 0u, 464 DE_NULL, 465 466 (deUint32)extensions.size(), 467 extensions.empty() ? DE_NULL : &extensions[0], 468 0u 469 }; 470 471 return vk::createDevice(vki, physicalDevice, &createInfo); 472 } 473 catch (const vk::Error& error) 474 { 475 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT) 476 TCU_THROW(NotSupportedError, "Required extensions not supported"); 477 else 478 throw; 479 } 480 } 481 482 vk::VkQueue getQueue (const vk::DeviceInterface& vkd, 483 const vk::VkDevice device, 484 deUint32 familyIndex) 485 { 486 vk::VkQueue queue; 487 488 vkd.getDeviceQueue(device, familyIndex, 0u, &queue); 489 490 return queue; 491 } 492 493 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd, 494 vk::VkDevice device, 495 deUint32 queueFamilyIndex) 496 { 497 const vk::VkCommandPoolCreateInfo createInfo = 498 { 499 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 500 DE_NULL, 501 502 0u, 503 queueFamilyIndex 504 }; 505 506 return vk::createCommandPool(vkd, device, &createInfo); 507 } 508 509 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd, 510 vk::VkDevice device, 511 vk::VkCommandPool commandPool) 512 { 513 const vk::VkCommandBufferLevel level = vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY; 514 const vk::VkCommandBufferAllocateInfo allocateInfo = 515 { 516 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 517 DE_NULL, 518 519 commandPool, 520 level, 521 1u 522 }; 523 524 return vk::allocateCommandBuffer(vkd, device, &allocateInfo); 525 } 526 527 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd, 528 vk::VkDevice device, 529 vk::VkBuffer buffer, 530 vk::VkExternalMemoryHandleTypeFlagBits externalType, 531 deUint32& exportedMemoryTypeIndex, 532 bool dedicated, 533 bool getMemReq2Supported) 534 { 535 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, }; 536 537 if (getMemReq2Supported) 538 { 539 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo = 540 { 541 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, 542 DE_NULL, 543 buffer 544 }; 545 vk::VkMemoryDedicatedRequirements dedicatedRequirements = 546 { 547 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, 548 DE_NULL, 549 VK_FALSE, 550 VK_FALSE 551 }; 552 vk::VkMemoryRequirements2 requirements = 553 { 554 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, 555 &dedicatedRequirements, 556 { 0u, 0u, 0u, } 557 }; 558 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements); 559 560 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation) 561 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation"); 562 563 memoryRequirements = requirements.memoryRequirements; 564 } 565 else 566 { 567 vkd.getBufferMemoryRequirements(device, buffer, &memoryRequirements); 568 } 569 570 571 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, memoryRequirements, externalType, dedicated ? buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex); 572 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u)); 573 574 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown())); 575 } 576 577 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd, 578 vk::VkDevice device, 579 vk::VkImage image, 580 vk::VkExternalMemoryHandleTypeFlagBits externalType, 581 deUint32& exportedMemoryTypeIndex, 582 bool dedicated, 583 bool getMemReq2Supported) 584 { 585 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, }; 586 587 if (getMemReq2Supported) 588 { 589 const vk::VkImageMemoryRequirementsInfo2 requirementInfo = 590 { 591 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, 592 DE_NULL, 593 image 594 }; 595 vk::VkMemoryDedicatedRequirements dedicatedRequirements = 596 { 597 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, 598 DE_NULL, 599 VK_FALSE, 600 VK_FALSE 601 }; 602 vk::VkMemoryRequirements2 requirements = 603 { 604 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, 605 &dedicatedRequirements, 606 { 0u, 0u, 0u, } 607 }; 608 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements); 609 610 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation) 611 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation"); 612 613 memoryRequirements = requirements.memoryRequirements; 614 } 615 else 616 { 617 vkd.getImageMemoryRequirements(device, image, &memoryRequirements); 618 } 619 620 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, memoryRequirements, externalType, dedicated ? image : (vk::VkImage)0, exportedMemoryTypeIndex); 621 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u)); 622 623 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown())); 624 } 625 626 de::MovePtr<Resource> createResource (const vk::DeviceInterface& vkd, 627 vk::VkDevice device, 628 const ResourceDescription& resourceDesc, 629 const std::vector<deUint32>& queueFamilyIndices, 630 const OperationSupport& readOp, 631 const OperationSupport& writeOp, 632 vk::VkExternalMemoryHandleTypeFlagBits externalType, 633 deUint32& exportedMemoryTypeIndex, 634 bool dedicated, 635 bool getMemReq2Supported) 636 { 637 if (resourceDesc.type == RESOURCE_TYPE_IMAGE) 638 { 639 const vk::VkExtent3D extent = 640 { 641 (deUint32)resourceDesc.size.x(), 642 de::max(1u, (deUint32)resourceDesc.size.y()), 643 de::max(1u, (deUint32)resourceDesc.size.z()) 644 }; 645 const vk::VkImageSubresourceRange subresourceRange = 646 { 647 resourceDesc.imageAspect, 648 0u, 649 1u, 650 0u, 651 1u 652 }; 653 const vk::VkImageSubresourceLayers subresourceLayers = 654 { 655 resourceDesc.imageAspect, 656 0u, 657 0u, 658 1u 659 }; 660 const vk::VkExternalMemoryImageCreateInfo externalInfo = 661 { 662 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 663 DE_NULL, 664 (vk::VkExternalMemoryHandleTypeFlags)externalType 665 }; 666 const vk::VkImageCreateInfo createInfo = 667 { 668 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 669 &externalInfo, 670 0u, 671 672 resourceDesc.imageType, 673 resourceDesc.imageFormat, 674 extent, 675 1u, 676 1u, 677 vk::VK_SAMPLE_COUNT_1_BIT, 678 vk::VK_IMAGE_TILING_OPTIMAL, 679 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(), 680 vk::VK_SHARING_MODE_EXCLUSIVE, 681 682 (deUint32)queueFamilyIndices.size(), 683 &queueFamilyIndices[0], 684 vk::VK_IMAGE_LAYOUT_UNDEFINED 685 }; 686 687 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo); 688 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *image, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported); 689 690 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers)); 691 } 692 else 693 { 694 const vk::VkDeviceSize offset = 0u; 695 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x()); 696 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(); 697 const vk:: VkExternalMemoryBufferCreateInfo externalInfo = 698 { 699 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, 700 DE_NULL, 701 (vk::VkExternalMemoryHandleTypeFlags)externalType 702 }; 703 const vk::VkBufferCreateInfo createInfo = 704 { 705 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 706 &externalInfo, 707 0u, 708 709 size, 710 usage, 711 vk::VK_SHARING_MODE_EXCLUSIVE, 712 (deUint32)queueFamilyIndices.size(), 713 &queueFamilyIndices[0] 714 }; 715 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo); 716 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *buffer, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported); 717 718 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size)); 719 } 720 } 721 722 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd, 723 vk::VkDevice device, 724 vk::VkBuffer buffer, 725 NativeHandle& nativeHandle, 726 vk::VkExternalMemoryHandleTypeFlagBits externalType, 727 deUint32 exportedMemoryTypeIndex, 728 bool dedicated) 729 { 730 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vkd, device, buffer); 731 vk::Move<vk::VkDeviceMemory> memory = dedicated 732 ? importDedicatedMemory(vkd, device, buffer, requirements, externalType, exportedMemoryTypeIndex, nativeHandle) 733 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle); 734 735 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u)); 736 737 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown())); 738 } 739 740 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd, 741 vk::VkDevice device, 742 vk::VkImage image, 743 NativeHandle& nativeHandle, 744 vk::VkExternalMemoryHandleTypeFlagBits externalType, 745 deUint32 exportedMemoryTypeIndex, 746 bool dedicated) 747 { 748 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vkd, device, image); 749 vk::Move<vk::VkDeviceMemory> memory = dedicated 750 ? importDedicatedMemory(vkd, device, image, requirements, externalType, exportedMemoryTypeIndex, nativeHandle) 751 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle); 752 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u)); 753 754 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown())); 755 } 756 757 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd, 758 vk::VkDevice device, 759 const ResourceDescription& resourceDesc, 760 const std::vector<deUint32>& queueFamilyIndices, 761 const OperationSupport& readOp, 762 const OperationSupport& writeOp, 763 NativeHandle& nativeHandle, 764 vk::VkExternalMemoryHandleTypeFlagBits externalType, 765 deUint32 exportedMemoryTypeIndex, 766 bool dedicated) 767 { 768 if (resourceDesc.type == RESOURCE_TYPE_IMAGE) 769 { 770 const vk::VkExtent3D extent = 771 { 772 (deUint32)resourceDesc.size.x(), 773 de::max(1u, (deUint32)resourceDesc.size.y()), 774 de::max(1u, (deUint32)resourceDesc.size.z()) 775 }; 776 const vk::VkImageSubresourceRange subresourceRange = 777 { 778 resourceDesc.imageAspect, 779 0u, 780 1u, 781 0u, 782 1u 783 }; 784 const vk::VkImageSubresourceLayers subresourceLayers = 785 { 786 resourceDesc.imageAspect, 787 0u, 788 0u, 789 1u 790 }; 791 const vk:: VkExternalMemoryImageCreateInfo externalInfo = 792 { 793 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 794 DE_NULL, 795 (vk::VkExternalMemoryHandleTypeFlags)externalType 796 }; 797 const vk::VkImageCreateInfo createInfo = 798 { 799 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 800 &externalInfo, 801 0u, 802 803 resourceDesc.imageType, 804 resourceDesc.imageFormat, 805 extent, 806 1u, 807 1u, 808 vk::VK_SAMPLE_COUNT_1_BIT, 809 vk::VK_IMAGE_TILING_OPTIMAL, 810 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(), 811 vk::VK_SHARING_MODE_EXCLUSIVE, 812 813 (deUint32)queueFamilyIndices.size(), 814 &queueFamilyIndices[0], 815 vk::VK_IMAGE_LAYOUT_UNDEFINED 816 }; 817 818 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo); 819 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated); 820 821 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers)); 822 } 823 else 824 { 825 const vk::VkDeviceSize offset = 0u; 826 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x()); 827 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(); 828 const vk:: VkExternalMemoryBufferCreateInfo externalInfo = 829 { 830 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, 831 DE_NULL, 832 (vk::VkExternalMemoryHandleTypeFlags)externalType 833 }; 834 const vk::VkBufferCreateInfo createInfo = 835 { 836 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 837 &externalInfo, 838 0u, 839 840 size, 841 usage, 842 vk::VK_SHARING_MODE_EXCLUSIVE, 843 (deUint32)queueFamilyIndices.size(), 844 &queueFamilyIndices[0] 845 }; 846 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo); 847 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated); 848 849 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size)); 850 } 851 } 852 853 void recordWriteBarrier (const vk::DeviceInterface& vkd, 854 vk::VkCommandBuffer commandBuffer, 855 const Resource& resource, 856 const SyncInfo& writeSync, 857 deUint32 writeQueueFamilyIndex, 858 const SyncInfo& readSync) 859 { 860 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask; 861 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask; 862 863 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask; 864 const vk::VkAccessFlags dstAccessMask = readSync.accessMask; 865 866 const vk::VkDependencyFlags dependencyFlags = 0; 867 868 if (resource.getType() == RESOURCE_TYPE_IMAGE) 869 { 870 const vk::VkImageMemoryBarrier barrier = 871 { 872 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 873 DE_NULL, 874 875 srcAccessMask, 876 dstAccessMask, 877 878 writeSync.imageLayout, 879 readSync.imageLayout, 880 881 writeQueueFamilyIndex, 882 VK_QUEUE_FAMILY_EXTERNAL, 883 884 resource.getImage().handle, 885 resource.getImage().subresourceRange 886 }; 887 888 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier); 889 } 890 else 891 { 892 const vk::VkBufferMemoryBarrier barrier = 893 { 894 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 895 DE_NULL, 896 897 srcAccessMask, 898 dstAccessMask, 899 900 writeQueueFamilyIndex, 901 VK_QUEUE_FAMILY_EXTERNAL, 902 903 resource.getBuffer().handle, 904 0u, 905 VK_WHOLE_SIZE 906 }; 907 908 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL); 909 } 910 } 911 912 void recordReadBarrier (const vk::DeviceInterface& vkd, 913 vk::VkCommandBuffer commandBuffer, 914 const Resource& resource, 915 const SyncInfo& writeSync, 916 const SyncInfo& readSync, 917 deUint32 readQueueFamilyIndex) 918 { 919 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask; 920 const vk::VkAccessFlags srcAccessMask = readSync.accessMask; 921 922 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask; 923 const vk::VkAccessFlags dstAccessMask = readSync.accessMask; 924 925 const vk::VkDependencyFlags dependencyFlags = 0; 926 927 if (resource.getType() == RESOURCE_TYPE_IMAGE) 928 { 929 const vk::VkImageMemoryBarrier barrier = 930 { 931 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 932 DE_NULL, 933 934 srcAccessMask, 935 dstAccessMask, 936 937 writeSync.imageLayout, 938 readSync.imageLayout, 939 940 VK_QUEUE_FAMILY_EXTERNAL, 941 readQueueFamilyIndex, 942 943 resource.getImage().handle, 944 resource.getImage().subresourceRange 945 }; 946 947 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier); 948 } 949 else 950 { 951 const vk::VkBufferMemoryBarrier barrier = 952 { 953 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 954 DE_NULL, 955 956 srcAccessMask, 957 dstAccessMask, 958 959 VK_QUEUE_FAMILY_EXTERNAL, 960 readQueueFamilyIndex, 961 962 resource.getBuffer().handle, 963 0u, 964 VK_WHOLE_SIZE 965 }; 966 967 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL); 968 } 969 } 970 971 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties) 972 { 973 std::vector<deUint32> indices (properties.size(), 0); 974 975 for (deUint32 ndx = 0; ndx < properties.size(); ndx++) 976 indices[ndx] = ndx; 977 978 return indices; 979 } 980 981 class SharingTestInstance : public TestInstance 982 { 983 public: 984 SharingTestInstance (Context& context, 985 TestConfig config); 986 987 virtual tcu::TestStatus iterate (void); 988 989 private: 990 const TestConfig m_config; 991 const de::UniquePtr<OperationSupport> m_supportWriteOp; 992 const de::UniquePtr<OperationSupport> m_supportReadOp; 993 const NotSupportedChecker m_notSupportedChecker; // Must declare before VkInstance to effectively reduce runtimes! 994 995 const vk::Unique<vk::VkInstance> m_instanceA; 996 997 const vk::InstanceDriver m_vkiA; 998 const vk::VkPhysicalDevice m_physicalDeviceA; 999 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesA; 1000 const std::vector<deUint32> m_queueFamilyIndicesA; 1001 1002 const bool m_getMemReq2Supported; 1003 1004 const vk::Unique<vk::VkDevice> m_deviceA; 1005 const vk::DeviceDriver m_vkdA; 1006 1007 const vk::Unique<vk::VkInstance> m_instanceB; 1008 const vk::InstanceDriver m_vkiB; 1009 const vk::VkPhysicalDevice m_physicalDeviceB; 1010 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesB; 1011 const std::vector<deUint32> m_queueFamilyIndicesB; 1012 const vk::Unique<vk::VkDevice> m_deviceB; 1013 const vk::DeviceDriver m_vkdB; 1014 1015 const vk::VkExternalSemaphoreHandleTypeFlagBits m_semaphoreHandleType; 1016 const vk::VkExternalMemoryHandleTypeFlagBits m_memoryHandleType; 1017 1018 // \todo Should this be moved to the group same way as in the other tests? 1019 PipelineCacheData m_pipelineCacheData; 1020 tcu::ResultCollector m_resultCollector; 1021 size_t m_queueANdx; 1022 size_t m_queueBNdx; 1023 }; 1024 1025 SharingTestInstance::SharingTestInstance (Context& context, 1026 TestConfig config) 1027 : TestInstance (context) 1028 , m_config (config) 1029 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource)) 1030 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource)) 1031 , m_notSupportedChecker (context, m_config, *m_supportWriteOp, *m_supportReadOp) 1032 1033 , m_instanceA (createInstance(context.getPlatformInterface(), context.getUsedApiVersion())) 1034 1035 , m_vkiA (context.getPlatformInterface(), *m_instanceA) // \todo [2017-06-13 pyry] Provide correct extension list 1036 , m_physicalDeviceA (getPhysicalDevice(m_vkiA, *m_instanceA, context.getTestContext().getCommandLine())) 1037 , m_queueFamiliesA (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA)) 1038 , m_queueFamilyIndicesA (getFamilyIndices(m_queueFamiliesA)) 1039 , m_getMemReq2Supported (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_get_memory_requirements2")) 1040 , m_deviceA (createDevice(context.getUsedApiVersion(), m_vkiA, m_physicalDeviceA, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported)) 1041 , m_vkdA (m_vkiA, *m_deviceA) 1042 1043 , m_instanceB (createInstance(context.getPlatformInterface(), context.getUsedApiVersion())) 1044 1045 , m_vkiB (context.getPlatformInterface(), *m_instanceB) // \todo [2017-06-13 pyry] Provide correct extension list 1046 , m_physicalDeviceB (getPhysicalDevice(m_vkiB, *m_instanceB, getDeviceId(m_vkiA, m_physicalDeviceA))) 1047 , m_queueFamiliesB (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB)) 1048 , m_queueFamilyIndicesB (getFamilyIndices(m_queueFamiliesB)) 1049 , m_deviceB (createDevice(context.getUsedApiVersion(), m_vkiB, m_physicalDeviceB, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported)) 1050 , m_vkdB (m_vkiB, *m_deviceB) 1051 1052 , m_semaphoreHandleType (m_config.semaphoreHandleType) 1053 , m_memoryHandleType (m_config.memoryHandleType) 1054 1055 , m_resultCollector (context.getTestContext().getLog()) 1056 , m_queueANdx (0) 1057 , m_queueBNdx (0) 1058 { 1059 } 1060 1061 tcu::TestStatus SharingTestInstance::iterate (void) 1062 { 1063 TestLog& log (m_context.getTestContext().getLog()); 1064 1065 try 1066 { 1067 const deUint32 queueFamilyA = (deUint32)m_queueANdx; 1068 const deUint32 queueFamilyB = (deUint32)m_queueBNdx; 1069 1070 const tcu::ScopedLogSection queuePairSection (log, 1071 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB), 1072 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB)); 1073 1074 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(m_vkdA, *m_deviceA, m_semaphoreHandleType)); 1075 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(m_vkdB, *m_deviceB)); 1076 1077 deUint32 exportedMemoryTypeIndex = ~0U; 1078 const de::UniquePtr<Resource> resourceA (createResource(m_vkdA, *m_deviceA, m_config.resource, m_queueFamilyIndicesA, *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated, m_getMemReq2Supported)); 1079 1080 NativeHandle nativeMemoryHandle; 1081 getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle); 1082 1083 const de::UniquePtr<Resource> resourceB (importResource(m_vkdB, *m_deviceB, m_config.resource, m_queueFamilyIndicesB, *m_supportReadOp, *m_supportWriteOp, nativeMemoryHandle, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated)); 1084 1085 1086 const vk::VkQueue queueA (getQueue(m_vkdA, *m_deviceA, queueFamilyA)); 1087 const vk::Unique<vk::VkCommandPool> commandPoolA (createCommandPool(m_vkdA, *m_deviceA, queueFamilyA)); 1088 const vk::Unique<vk::VkCommandBuffer> commandBufferA (createCommandBuffer(m_vkdA, *m_deviceA, *commandPoolA)); 1089 vk::SimpleAllocator allocatorA (m_vkdA, *m_deviceA, vk::getPhysicalDeviceMemoryProperties(m_vkiA, m_physicalDeviceA)); 1090 const std::vector<std::string> deviceExtensionsA; 1091 OperationContext operationContextA (m_context.getUsedApiVersion(), m_vkiA, m_vkdA, m_physicalDeviceA, *m_deviceA, allocatorA, deviceExtensionsA, m_context.getBinaryCollection(), m_pipelineCacheData); 1092 1093 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA))) 1094 TCU_THROW(NotSupportedError, "Operation not supported by the source queue"); 1095 1096 const vk::VkQueue queueB (getQueue(m_vkdB, *m_deviceB, queueFamilyB)); 1097 const vk::Unique<vk::VkCommandPool> commandPoolB (createCommandPool(m_vkdB, *m_deviceB, queueFamilyB)); 1098 const vk::Unique<vk::VkCommandBuffer> commandBufferB (createCommandBuffer(m_vkdB, *m_deviceB, *commandPoolB)); 1099 vk::SimpleAllocator allocatorB (m_vkdB, *m_deviceB, vk::getPhysicalDeviceMemoryProperties(m_vkiB, m_physicalDeviceB)); 1100 const std::vector<std::string> deviceExtensionsB; 1101 OperationContext operationContextB (m_context.getUsedApiVersion(), m_vkiB, m_vkdB, m_physicalDeviceB, *m_deviceB, allocatorB, deviceExtensionsB, m_context.getBinaryCollection(), m_pipelineCacheData); 1102 1103 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB))) 1104 TCU_THROW(NotSupportedError, "Operation not supported by the destination queue"); 1105 1106 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContextA, *resourceA)); 1107 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContextB, *resourceB)); 1108 1109 const SyncInfo writeSync = writeOp->getSyncInfo(); 1110 const SyncInfo readSync = readOp->getSyncInfo(); 1111 1112 beginCommandBuffer(m_vkdA, *commandBufferA); 1113 writeOp->recordCommands(*commandBufferA); 1114 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync); 1115 endCommandBuffer(m_vkdA, *commandBufferA); 1116 1117 beginCommandBuffer(m_vkdB, *commandBufferB); 1118 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB); 1119 readOp->recordCommands(*commandBufferB); 1120 endCommandBuffer(m_vkdB, *commandBufferB); 1121 1122 { 1123 const vk::VkCommandBuffer commandBuffer = *commandBufferA; 1124 const vk::VkSemaphore semaphore = *semaphoreA; 1125 const vk::VkSubmitInfo submitInfo = 1126 { 1127 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 1128 DE_NULL, 1129 1130 0u, 1131 DE_NULL, 1132 DE_NULL, 1133 1134 1u, 1135 &commandBuffer, 1136 1u, 1137 &semaphore 1138 }; 1139 1140 VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL)); 1141 1142 { 1143 NativeHandle nativeSemaphoreHandle; 1144 1145 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle); 1146 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u); 1147 } 1148 } 1149 { 1150 const vk::VkCommandBuffer commandBuffer = *commandBufferB; 1151 const vk::VkSemaphore semaphore = *semaphoreB; 1152 const vk::VkPipelineStageFlags dstStage = readSync.stageMask; 1153 const vk::VkSubmitInfo submitInfo = 1154 { 1155 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 1156 DE_NULL, 1157 1158 1u, 1159 &semaphore, 1160 &dstStage, 1161 1162 1u, 1163 &commandBuffer, 1164 0u, 1165 DE_NULL, 1166 }; 1167 1168 VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL)); 1169 } 1170 1171 VK_CHECK(m_vkdA.queueWaitIdle(queueA)); 1172 VK_CHECK(m_vkdB.queueWaitIdle(queueB)); 1173 1174 { 1175 const Data expected = writeOp->getData(); 1176 const Data actual = readOp->getData(); 1177 1178 DE_ASSERT(expected.size == actual.size); 1179 1180 if (0 != deMemCmp(expected.data, actual.data, expected.size)) 1181 { 1182 const size_t maxBytesLogged = 256; 1183 std::ostringstream expectedData; 1184 std::ostringstream actualData; 1185 size_t byteNdx = 0; 1186 1187 // Find first byte difference 1188 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++) 1189 { 1190 // Nothing 1191 } 1192 1193 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage; 1194 1195 // Log 8 previous bytes before the first incorrect byte 1196 if (byteNdx > 8) 1197 { 1198 expectedData << "... "; 1199 actualData << "... "; 1200 1201 byteNdx -= 8; 1202 } 1203 else 1204 byteNdx = 0; 1205 1206 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++) 1207 { 1208 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx]; 1209 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx]; 1210 } 1211 1212 if (expected.size > byteNdx) 1213 { 1214 expectedData << "..."; 1215 actualData << "..."; 1216 } 1217 1218 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage; 1219 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage; 1220 1221 m_resultCollector.fail("Memory contents don't match"); 1222 } 1223 } 1224 } 1225 catch (const tcu::NotSupportedError& error) 1226 { 1227 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage; 1228 } 1229 catch (const tcu::TestError& error) 1230 { 1231 m_resultCollector.fail(std::string("Exception: ") + error.getMessage()); 1232 } 1233 1234 // Move to next queue 1235 { 1236 m_queueBNdx++; 1237 1238 if (m_queueBNdx >= m_queueFamiliesB.size()) 1239 { 1240 m_queueANdx++; 1241 1242 if (m_queueANdx >= m_queueFamiliesA.size()) 1243 { 1244 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); 1245 } 1246 else 1247 { 1248 m_queueBNdx = 0; 1249 1250 return tcu::TestStatus::incomplete(); 1251 } 1252 } 1253 else 1254 return tcu::TestStatus::incomplete(); 1255 } 1256 } 1257 1258 struct Progs 1259 { 1260 void init (vk::SourceCollections& dst, TestConfig config) const 1261 { 1262 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource)); 1263 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource)); 1264 1265 readOp->initPrograms(dst); 1266 writeOp->initPrograms(dst); 1267 } 1268 }; 1269 1270 } // anonymous 1271 1272 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx) 1273 { 1274 const struct 1275 { 1276 vk::VkExternalMemoryHandleTypeFlagBits memoryType; 1277 vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreType; 1278 const char* nameSuffix; 1279 } cases[] = 1280 { 1281 { 1282 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, 1283 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, 1284 "_fd" 1285 }, 1286 { 1287 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, 1288 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 1289 "_fence_fd" 1290 }, 1291 { 1292 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, 1293 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, 1294 "_win32_kmt" 1295 }, 1296 { 1297 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, 1298 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT, 1299 "_win32" 1300 }, 1301 }; 1302 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", "")); 1303 1304 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++) 1305 { 1306 const bool dedicated (dedicatedNdx == 1); 1307 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", "")); 1308 1309 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx) 1310 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx) 1311 { 1312 const OperationName writeOp = s_writeOps[writeOpNdx]; 1313 const OperationName readOp = s_readOps[readOpNdx]; 1314 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp); 1315 bool empty = true; 1316 1317 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), "")); 1318 1319 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx) 1320 { 1321 const ResourceDescription& resource = s_resources[resourceNdx]; 1322 1323 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++) 1324 { 1325 std::string name= getResourceName(resource) + cases[caseNdx].nameSuffix; 1326 1327 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource)) 1328 { 1329 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated); 1330 1331 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config)); 1332 empty = false; 1333 } 1334 } 1335 } 1336 1337 if (!empty) 1338 dedicatedGroup->addChild(opGroup.release()); 1339 } 1340 1341 group->addChild(dedicatedGroup.release()); 1342 } 1343 1344 return group.release(); 1345 } 1346 1347 } // synchronization 1348 } // vkt 1349