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